v4l2.c
Upload User: shyika
Upload Date: 2017-11-25
Package Size: 1227k
Code Size: 57k
Category:

Video Capture

Development Platform:

Unix_Linux

  1. /*
  2.   unicap
  3.   Copyright (C) 2004  Arne Caspari
  4.   This program is free software; you can redistribute it and/or modify
  5.   it under the terms of the GNU General Public License as published by
  6.   the Free Software Foundation; either version 2 of the License, or
  7.   (at your option) any later version.
  8.   This program is distributed in the hope that it will be useful,
  9.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.   GNU General Public License for more details.
  12.  
  13.   You should have received a copy of the GNU General Public License
  14.   along with this program; if not, write to the Free Software
  15.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  16. */
  17. #define N_(x) x
  18. #include "config.h"
  19. #include <unicap.h>
  20. #include <unicap_status.h>
  21. #include <unicap_cpi.h>
  22. #include "queue.h"
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/mman.h>
  31. #include <fcntl.h>
  32. #include <dirent.h>
  33. #include <semaphore.h>
  34. #include <errno.h>
  35. #include <pthread.h>
  36. #include <linux/types.h>
  37. #include <linux/videodev2.h>
  38. #include "v4l2.h"
  39. #include "tisuvccam.h"
  40. #if V4L2_DEBUG
  41. #define DEBUG
  42. #endif
  43. #include "debug.h"
  44. #define V4L2_VIDEO_IN_PPTY_NAME   N_("video source")
  45. #define V4L2_VIDEO_NORM_PPTY_NAME N_("video norm")
  46. #define V4L2_VIDEO_FRAMERATE_PPTY_NAME N_("frame rate")
  47. struct prop_category
  48. {
  49.       char *property_id;
  50.       char *category;
  51. };
  52. struct fourcc_bpp
  53. {
  54.       __u32 fourcc;
  55.       int bpp;
  56. };
  57. static struct v4l2_uc_compat v4l2_uc_compat_list[] = 
  58. {
  59.    { 
  60.       driver: "uvcvideo", 
  61.       probe_func: tisuvccam_probe,
  62.       count_ext_property_func: tisuvccam_count_ext_property, 
  63.       enumerate_property_func: tisuvccam_enumerate_properties,
  64.       override_property_func: tisuvccam_override_property,
  65.       set_property_func: tisuvccam_set_property,
  66.       get_property_func: tisuvccam_get_property,
  67.       fmt_get_func: tisuvccam_fmt_get
  68.    },
  69.    
  70. };
  71. static struct fourcc_bpp fourcc_bpp_map[] =
  72. {
  73.    { V4L2_PIX_FMT_GREY,     8 },
  74.    { V4L2_PIX_FMT_YUYV,    16 },
  75.    { V4L2_PIX_FMT_UYVY,    16 },
  76.    { V4L2_PIX_FMT_Y41P,    12 },
  77.    { V4L2_PIX_FMT_YVU420,  12 },
  78.    { V4L2_PIX_FMT_YUV420,  12 },
  79.    { V4L2_PIX_FMT_YVU410,   9 },
  80.    { V4L2_PIX_FMT_YUV410,   9 },
  81.    { V4L2_PIX_FMT_YUV422P, 16 },
  82.    { V4L2_PIX_FMT_YUV411P, 12 },
  83.    { V4L2_PIX_FMT_NV12,    12 },
  84.    { V4L2_PIX_FMT_NV21,    12 },
  85.    { V4L2_PIX_FMT_YYUV,    16 },
  86.    { V4L2_PIX_FMT_HI240,    8 },
  87.    { V4L2_PIX_FMT_RGB332,   8 },
  88.    { V4L2_PIX_FMT_RGB555,  16 },
  89.    { V4L2_PIX_FMT_RGB565,  16 },
  90.    { V4L2_PIX_FMT_RGB555X, 16 },
  91.    { V4L2_PIX_FMT_RGB565X, 16 },
  92.    { V4L2_PIX_FMT_BGR24,   24 },
  93.    { V4L2_PIX_FMT_RGB24,   24 },
  94.    { V4L2_PIX_FMT_BGR32,   32 },
  95.    { V4L2_PIX_FMT_RGB32,   32 },
  96.    { FOURCC( 'Y', '8', '0', '0' ), 8 }, 
  97.    { FOURCC( 'B', 'Y', '8', ' ' ), 8 },
  98. };
  99. struct size_map_s
  100. {
  101.       char *card_name;
  102.       unicap_rect_t *sizes;
  103.       int size_count;
  104. };
  105. static unicap_rect_t try_sizes[] =
  106. {
  107.    { 0,0, 160, 120 }, 
  108.    { 0,0, 320, 240 }, 
  109.    { 0,0, 384, 288 }, 
  110.    { 0,0, 640, 480 }, 
  111.    { 0,0, 720, 480 },
  112.    { 0,0, 720, 576 },
  113.    { 0,0, 768, 576 },
  114.    { 0,0, 800, 600 },
  115.    { 0,0, 1024, 768 },
  116.    { 0,0, 1280, 960 },
  117. };
  118. static unicap_rect_t webcam_sizes[] =
  119. {
  120.    { 0,0, 160, 120 }, 
  121.    { 0,0, 320, 240 },
  122.    { 0,0, 352, 288 }, 
  123.    { 0,0, 640, 480 }, 
  124.    { 0,0, 748, 480 },
  125. };
  126. static unicap_rect_t dxx41_sizes[] =
  127. {
  128.    { 0,0, 1280, 960 }, 
  129. };
  130.   
  131. static struct size_map_s format_size_map[] = 
  132. {
  133.    { N_("STK-1135 USB2 Camera Controller"), webcam_sizes, sizeof( webcam_sizes ) / sizeof( unicap_rect_t ) },
  134.    { N_("DFx 41"), dxx41_sizes, sizeof( dxx41_sizes ) / sizeof( unicap_rect_t ) },
  135. };
  136. static unicap_status_t v4l2_enum_frameintervals( v4l2_handle_t handle, unicap_property_t *property );
  137. static unicap_status_t v4l2_enumerate_devices( unicap_device_t *device, int index );
  138. static unicap_status_t v4l2_open( void **cpi_data, unicap_device_t *device );
  139. static unicap_status_t v4l2_close( void *cpi_data );
  140. static unicap_status_t v4l2_reenumerate_formats( void *cpi_data, int *_pcount );
  141. static unicap_status_t v4l2_enumerate_formats( void *cpi_data, 
  142.        unicap_format_t *format, int index );
  143. static unicap_status_t v4l2_set_format( void *cpi_data, unicap_format_t *format );
  144. static unicap_status_t v4l2_get_format( void *cpi_data, unicap_format_t *format );
  145. static unicap_status_t v4l2_reenumerate_properties( void *cpi_data, int *_pcount );
  146. static unicap_status_t v4l2_enumerate_properties( void *cpi_data, 
  147.   unicap_property_t *property, int index );
  148. static unicap_status_t v4l2_set_property( void *cpi_data, unicap_property_t *property );
  149. static unicap_status_t v4l2_get_property( void *cpi_data, unicap_property_t *property );
  150. static unicap_status_t v4l2_capture_start( void *cpi_data );
  151. static unicap_status_t v4l2_capture_stop( void *cpi_data );
  152. static unicap_status_t v4l2_queue_buffer( void *cpi_data, unicap_data_buffer_t *buffer );
  153. static unicap_status_t v4l2_dequeue_buffer( void *cpi_data, unicap_data_buffer_t **buffer );
  154. static unicap_status_t v4l2_wait_buffer( void *cpi_data, unicap_data_buffer_t **buffer );
  155. static unicap_status_t v4l2_poll_buffer( void *cpi_data, int *count );
  156. static unicap_status_t v4l2_set_event_notify( void *cpi_data, 
  157.       unicap_event_callback_t func, 
  158.       unicap_handle_t unicap_handle );
  159. static unicap_status_t queue_buffer( v4l2_handle_t handle, unicap_data_buffer_t *buffer );
  160. static unicap_status_t queue_system_buffers( v4l2_handle_t handle );
  161. static void v4l2_capture_thread( v4l2_handle_t handle );
  162. static struct _unicap_cpi cpi_s = 
  163. {
  164.    cpi_version: 1<<16,
  165.    cpi_capabilities: 0x3ffff,
  166.    cpi_enumerate_devices: v4l2_enumerate_devices,
  167.    cpi_open: v4l2_open, 
  168.    cpi_close: v4l2_close,
  169.    cpi_reenumerate_formats: v4l2_reenumerate_formats, 
  170.    cpi_enumerate_formats: v4l2_enumerate_formats,   
  171.    cpi_set_format: v4l2_set_format,    
  172.    cpi_get_format: v4l2_get_format,          
  173.    cpi_reenumerate_properties: v4l2_reenumerate_properties,
  174.    cpi_enumerate_properties: v4l2_enumerate_properties,
  175.    cpi_set_property: v4l2_set_property,
  176.    cpi_get_property: v4l2_get_property,
  177.    cpi_capture_start: v4l2_capture_start,
  178.    cpi_capture_stop: v4l2_capture_stop,
  179.    
  180.    cpi_queue_buffer: v4l2_queue_buffer,
  181.    cpi_dequeue_buffer: v4l2_dequeue_buffer,
  182.    cpi_wait_buffer: v4l2_wait_buffer,
  183.    cpi_poll_buffer: v4l2_poll_buffer,
  184.    cpi_set_event_notify: v4l2_set_event_notify,
  185. };
  186. #if ENABLE_STATIC_CPI
  187. void unicap_v4l2_register_static_cpi( struct _unicap_cpi **cpi )
  188. {
  189.    *cpi = &cpi_s;
  190. }
  191. #else
  192. unicap_status_t cpi_register( struct _unicap_cpi *reg_data )
  193. {
  194.    memcpy( reg_data, &cpi_s, sizeof( struct _unicap_cpi ) );
  195.    return STATUS_SUCCESS;
  196. }
  197. #endif//ENABLE_STATIC_CPI
  198. static unicap_status_t get_current_format( v4l2_handle_t handle, unicap_format_t *format )
  199. {
  200.    struct v4l2_cropcap v4l2_crop;
  201.    struct v4l2_format v4l2_fmt;
  202.    int i;
  203.    int index = -1;
  204.    unsigned int pixelformat;
  205.    v4l2_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  206.    v4l2_crop.defrect.width = v4l2_crop.bounds.width = 640;
  207.    v4l2_crop.defrect.height = v4l2_crop.bounds.height = 480;
  208.    v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  209.    if( ioctl( handle->fd, VIDIOC_G_FMT, &v4l2_fmt ) )
  210.    {
  211.       TRACE( "VIDIOC_G_FMT ioctl failed: %sn", strerror( errno ) );
  212.       return STATUS_FAILURE;
  213.    }
  214.    pixelformat = v4l2_fmt.fmt.pix.pixelformat;
  215.    for( i = 0; i < handle->format_count; i++ )
  216.    {
  217.       if( pixelformat == handle->unicap_formats[ i ].fourcc )
  218.       {
  219.  index = i;
  220.  break;
  221.       }
  222.    }
  223.    if( index == -1 )
  224.    {
  225.       TRACE( "v4l2 get format: format not in the list of currently known formats; pixelformat = %08xn", pixelformat );
  226.       return STATUS_FAILURE;
  227.    }
  228.    unicap_copy_format( format, &handle->unicap_formats[index] );
  229.    return STATUS_SUCCESS;
  230. }
  231. static int file_filter( const struct dirent *a )
  232. {
  233.    int match = 0;
  234.    
  235.    // match: 'videoXY' where X = {0..9} and Y = {0..9}
  236.    if( !strncmp( a->d_name, "video", 5 ) )
  237.    {
  238.       if( strlen( a->d_name ) > 5 )
  239.       {
  240.  if( ( a->d_name[5] >= '0' ) && ( a->d_name[5] <= '9' ) ) // match
  241.       // the 'X'
  242.  {
  243.     match = 1;
  244.  }
  245.  
  246.  if( strlen( a->d_name ) > 6 )
  247.  {
  248.     match = 0;
  249.     
  250.     if( ( a->d_name[6] >= '0' ) && ( a->d_name[6] <= '9' ) )
  251.     {
  252.        match = 1;
  253.     }
  254.  }
  255.  
  256.  if( strlen( a->d_name ) > 7 )
  257.  {
  258.     match = 0;
  259.  }
  260.       }
  261.    }
  262.    
  263.    return match;
  264. }
  265. static unicap_status_t v4l2_enumerate_devices( unicap_device_t *device, int index )
  266. {
  267.    int fd;
  268.    struct v4l2_capability v4l2caps;
  269.    struct dirent **namelist;
  270.    int n;
  271.    int found = -1;
  272.    char devname[512];
  273.    char ckey[512];
  274.       
  275.    TRACE( "v4l2_enumerate_devices[%d]n", index );
  276.    
  277.    n = scandir( "/dev", &namelist, file_filter, alphasort );
  278.    if( n < 0 )
  279.    {
  280.       TRACE( "Failed to scan directory '/dev' n" );
  281.       return STATUS_NO_DEVICE;
  282.    }
  283.    while( ( found != index ) && n-- )
  284.    {      
  285.       sprintf( devname, "/dev/%s", namelist[n]->d_name );
  286.       
  287. /*       free( namelist[n]->d_name ); */
  288.       TRACE( "v4l2: open %sn", devname );
  289.       if( ( fd = open( devname, O_RDONLY | O_NONBLOCK ) ) == -1 )
  290.       {
  291.  TRACE( "v4l2_cpi: open(%s): %sn", devname, strerror( errno ) );
  292.  continue;
  293.       }
  294.       
  295.       if( ioctl( fd, VIDIOC_QUERYCAP, &v4l2caps ) < 0 )
  296.       {
  297.  TRACE( "ioctl failedn" );
  298.  close( fd );
  299.  continue;
  300.       }
  301.       
  302.       if( !(v4l2caps.capabilities & V4L2_CAP_VIDEO_CAPTURE) )
  303.       {
  304.  // v4l version one device
  305.  close( fd );
  306.  continue;
  307.       }
  308.       found++;
  309.       close( fd );
  310.    }
  311. /*    free( namelist ); */
  312.    if( found != index )
  313.    {
  314.       return STATUS_NO_DEVICE;
  315.    }
  316.    sprintf( device->identifier, "%s (%s)", v4l2caps.card, v4l2caps.bus_info );
  317.    strcpy( device->model_name, (char*)v4l2caps.card );
  318.    strcpy( device->vendor_name, "v4l2");
  319.    device->model_id = 0x1;
  320.    device->vendor_id = 0xffff0000;
  321.    device->flags = UNICAP_CPI_SERIALIZED;
  322.    strcpy( device->device, devname ) ;  
  323.    return STATUS_SUCCESS;
  324. }
  325. static unicap_status_t v4l2_open( void **cpi_data, unicap_device_t *device )
  326. {
  327.    v4l2_handle_t handle = NULL;
  328.    struct v4l2_capability v4l2caps;
  329.    char identifier[128];
  330.    int i;
  331.    TRACE( "v4l2_openn" );
  332.    *cpi_data = malloc( sizeof( struct _v4l2_handle ) );
  333.    memset( *cpi_data, 0x0, sizeof( struct _v4l2_handle ) );
  334.    handle = (v4l2_handle_t) *cpi_data;   
  335.    if( sem_init( &handle->sema, 0, 1 ) )
  336.    {
  337.       TRACE( "sem_init failed!n" );
  338.       free( handle );
  339.       return STATUS_FAILURE;
  340.    }
  341.    handle->io_method = CPI_V4L2_IO_METHOD_MMAP;
  342.    handle->buffer_count = V4L2_NUM_BUFFERS;
  343.    handle->fd = open( device->device, O_RDWR );
  344.    
  345.    if( handle->fd == -1 )
  346.    {
  347.       TRACE( "v4l2 open failedn" );
  348.       free( handle );
  349.       return STATUS_FAILURE;
  350.    }
  351.    for( i = 0; i < V4L2_MAX_VIDEO_INPUTS; i++ )
  352.    {
  353.       handle->video_inputs[i] = malloc( 32 );
  354.    }
  355.    
  356.    for( i = 0; i < V4L2_MAX_VIDEO_NORMS; i++ )
  357.    {
  358.       handle->video_norms[i] = malloc( 32 );
  359.    }
  360.    memset( &v4l2caps, 0x0, sizeof( v4l2caps ) );
  361.    if( ioctl( handle->fd, VIDIOC_QUERYCAP, &v4l2caps ) < 0 )
  362.    {
  363.       TRACE( "ioctl failedn" );
  364.       for( i = 0; i < V4L2_MAX_VIDEO_INPUTS; i++ )
  365.       {
  366.  free( handle->video_inputs[i] );
  367.       }
  368.       for( i = 0; i < V4L2_MAX_VIDEO_NORMS; i++ )
  369.       {
  370.  free( handle->video_norms[i] );
  371.       }
  372.       free( handle );
  373.       return STATUS_FAILURE;
  374.    }
  375.    sprintf( identifier, "%s (%s)", v4l2caps.card, v4l2caps.bus_info );
  376.    
  377.    if( strcmp( identifier, device->identifier ) )
  378.    {
  379.       for( i = 0; i < V4L2_MAX_VIDEO_INPUTS; i++ )
  380.       {
  381.  free( handle->video_inputs[i] );
  382.       }
  383.       for( i = 0; i < V4L2_MAX_VIDEO_NORMS; i++ )
  384.       {
  385.  free( handle->video_norms[i] );
  386.       }
  387.       free( handle );
  388.       return STATUS_NO_MATCH;
  389.    }
  390.    strcpy( handle->card_name, v4l2caps.card );
  391.    for( i = 0; i < ( sizeof( v4l2_uc_compat_list ) / sizeof( struct v4l2_uc_compat ) ); i++ )
  392.    {
  393.       if( !strcmp( v4l2_uc_compat_list[i].driver, v4l2caps.driver ) )
  394.       {
  395.  if( v4l2_uc_compat_list[i].probe_func( handle->fd ) )
  396.  {
  397.     handle->compat = &v4l2_uc_compat_list[i];
  398.  }
  399.       }
  400.    }
  401.    v4l2_reenumerate_formats( handle, NULL );
  402.    v4l2_reenumerate_properties( handle, NULL );
  403.    handle->in_queue = malloc( sizeof( struct _unicap_queue ) );
  404.    _init_queue( handle->in_queue );
  405.    handle->out_queue = malloc( sizeof( struct _unicap_queue ) );
  406.    _init_queue( handle->out_queue );
  407.    get_current_format( handle, &handle->current_format );
  408.    return STATUS_SUCCESS;
  409. }
  410. static unicap_status_t v4l2_close( void *cpi_data )
  411. {
  412.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  413.    TRACE( "v4l2_closen" );
  414.    
  415.    close( handle->fd );
  416.    if( handle->unicap_formats )
  417.    {
  418.       int i;
  419.       
  420.       if( handle->sizes_allocated )
  421.       {
  422.  for( i = 0; i < handle->format_count; i++ )
  423.  {
  424.     if( handle->unicap_formats[i].sizes )
  425.     {
  426.        free( handle->unicap_formats[i].sizes );
  427.     }
  428.  }
  429.       }
  430.       free( handle->unicap_formats );
  431.       handle->unicap_formats = 0;
  432.    }
  433.    if( handle->unicap_properties )
  434.    {
  435.       free( handle->unicap_properties );
  436.       handle->unicap_properties = 0;
  437.    }
  438.    if( handle->control_ids )
  439.    {
  440.       free( handle->control_ids );
  441.       handle->control_ids = 0;
  442.    }
  443.    if( handle->unicap_handle )
  444.    {
  445.       free( handle->unicap_handle );
  446.    }
  447.    
  448.    sem_destroy( &handle->sema );
  449.    free( handle );
  450.    return STATUS_SUCCESS;
  451. }
  452. static int v4l2_get_bpp( struct v4l2_fmtdesc *fmt )
  453. {
  454.    int bpp = 0;
  455.    int i;
  456.    for( i = 0; i < ( sizeof( fourcc_bpp_map ) / sizeof( struct fourcc_bpp ) ); i++ )
  457.    {
  458.       if( fourcc_bpp_map[i].fourcc == fmt->pixelformat )
  459.       {
  460.  bpp = fourcc_bpp_map[i].bpp;
  461.  break;
  462.       }
  463.    }
  464.    return bpp;
  465. }
  466. static unicap_rect_t *try_enum_framesizes( v4l2_handle_t handle, __u32 fourcc, int *pcount )
  467. {
  468. #ifndef VIDIOC_ENUM_FRAMESIZES
  469.    TRACE( "ENUM_FRAMESIZES not supportedn" );
  470.    return NULL;
  471. #else
  472.    int nfound = 0;
  473.    struct v4l2_frmsizeenum frms;
  474.    unicap_rect_t *sizes;
  475.    
  476.    frms.pixel_format = fourcc;
  477.    
  478.    for( frms.index = 0; ioctl( handle->fd, VIDIOC_ENUM_FRAMESIZES, &frms ) == 0; frms.index++ )
  479.    {
  480.       if( frms.type == V4L2_FRMSIZE_TYPE_DISCRETE )
  481.       {
  482.  nfound++;
  483.       }
  484.       else
  485.       {
  486.  TRACE( "VIDIOC_ENUM_FRAME_SIZES returned unsupported typen" );
  487.  return NULL;
  488.       }
  489.    }
  490.    
  491.    sizes = malloc( sizeof( unicap_rect_t ) * nfound );
  492.    
  493.    for( frms.index = 0; ( frms.index < nfound ) && ( ioctl( handle->fd, VIDIOC_ENUM_FRAMESIZES, &frms ) == 0 ); frms.index++ )
  494.    {
  495.       if( frms.type = V4L2_FRMSIZE_TYPE_DISCRETE )
  496.       {
  497.  sizes[frms.index].x = 0;
  498.  sizes[frms.index].y = 0;
  499.  sizes[frms.index].width = frms.discrete.width;
  500.  sizes[frms.index].height = frms.discrete.height;
  501.       }
  502.       else
  503.       {
  504.  TRACE( "VIDIOC_ENUM_FRAME_SIZES returned unsupported typen" );
  505.  return NULL;
  506.       }
  507.    }
  508.    TRACE( "found %d framesizes for fourcc: %08xn", nfound, fourcc );
  509.    
  510.    *pcount = nfound;
  511.    return sizes;
  512. #endif
  513. }
  514.    
  515. static unicap_rect_t *build_format_size_table( v4l2_handle_t handle, __u32 fourcc, int *pcount )
  516. {
  517.    int nfound = 0;
  518.    int i;
  519.    unicap_rect_t sfound[sizeof(try_sizes)/sizeof(unicap_rect_t)];
  520.    struct v4l2_format v4l2_fmt;
  521.    unicap_rect_t *sizes = NULL;
  522.    int n;
  523.    
  524.    handle->sizes_allocated = 1;
  525.    memset( sfound, 0x0, sizeof( sfound ) );
  526.    sizes = try_enum_framesizes( handle, fourcc, pcount );
  527.    if( sizes )
  528.    {
  529.       return sizes;
  530.    }
  531.    // First check whether the sizes for the device are already known
  532.    n = sizeof( format_size_map ) / sizeof( struct size_map_s );
  533.    for( i = 0; i < n; i++ )
  534.    {
  535.       if( !strncmp( format_size_map[i].card_name, handle->card_name, sizeof( format_size_map[i].card_name ) ) )
  536.       {
  537.  handle->sizes_allocated = 0;
  538.  *pcount = format_size_map[i].size_count;
  539.  return format_size_map[i].sizes;
  540.       }
  541.    } 
  542.    for( i = 0; i < sizeof(try_sizes)/sizeof(unicap_rect_t); i++ )
  543.    {
  544.       v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  545.       v4l2_fmt.fmt.pix.width = try_sizes[i].width;
  546.       v4l2_fmt.fmt.pix.height = try_sizes[i].height;
  547.       v4l2_fmt.fmt.pix.pixelformat = fourcc;
  548.       v4l2_fmt.fmt.pix.field = V4L2_FIELD_ANY;
  549.       if( ioctl( handle->fd, VIDIOC_S_FMT, &v4l2_fmt ) )
  550.       {
  551.  TRACE( "VIDIOC_S_FMT ioctl failed: %sn", strerror( errno ) );
  552.       }
  553.       else
  554.       {
  555.  int j;
  556.  int found_fmt = 0;
  557.  for( j = 0; j < nfound; j++ )
  558.  {
  559.     if( ( sfound[j].width == v4l2_fmt.fmt.pix.width ) &&
  560. ( sfound[j].height == v4l2_fmt.fmt.pix.height ) )
  561.     {
  562.        found_fmt = 1;
  563.        break;
  564.     }
  565.  }
  566.  
  567.  if( !found_fmt )
  568.  {
  569.     sfound[nfound].width = v4l2_fmt.fmt.pix.width;
  570.     sfound[nfound].height = v4l2_fmt.fmt.pix.height;
  571.     TRACE( "Found new size: %dx%dn", sfound[nfound].width, sfound[nfound].height );
  572.     nfound++;
  573.  }  
  574.       }
  575.    }
  576.    if( nfound )
  577.    {
  578.       sizes = malloc( sizeof( unicap_rect_t ) * nfound );
  579.       memcpy( sizes, sfound, nfound * sizeof( unicap_rect_t ) );
  580.    }
  581.    *pcount = nfound;
  582.    return sizes;
  583. }
  584. static unicap_status_t v4l2_reenumerate_formats( void *cpi_data, int *_pcount )
  585. {
  586.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  587.    int count;
  588.    struct v4l2_fmtdesc v4l2_fmt;
  589.    struct v4l2_cropcap v4l2_crop;
  590.    if( handle->unicap_formats && handle->sizes_allocated )
  591.    {
  592.       int i;
  593.       
  594.       for( i = 0; i < handle->format_count; i++ )
  595.       {
  596.  if( handle->unicap_formats[i].sizes )
  597.  {
  598.     free( handle->unicap_formats[i].sizes );
  599.  }
  600.       }
  601.       free( handle->unicap_formats );
  602.       handle->unicap_formats = 0;
  603.    }
  604.    // count the number of supported pixel formats
  605.    count = 0;
  606.    v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  607.    v4l2_fmt.index = 0;
  608.    while( !ioctl( handle->fd, VIDIOC_ENUM_FMT, &v4l2_fmt ) )
  609.    {
  610.       count++;
  611.       v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  612.       v4l2_fmt.index = count;
  613.    }
  614.    if( _pcount )
  615.    {
  616.       *_pcount = count;
  617.    }
  618.    if( !count )
  619.    {
  620.       return STATUS_FAILURE;
  621.    }
  622.    handle->unicap_formats = (unicap_format_t *) calloc( MAX_V4L2_FORMATS, sizeof( unicap_format_t ) );
  623.    v4l2_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  624.    // TODO: When CROPCAP is available --> use it 
  625.    if( ioctl( handle->fd, VIDIOC_CROPCAP, &v4l2_crop ) < 0 )
  626.    {
  627.       v4l2_crop.defrect.width = v4l2_crop.bounds.width = 640;
  628.       v4l2_crop.defrect.height = v4l2_crop.bounds.height = 480;
  629.    }
  630.    v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  631.    for( v4l2_fmt.index = 0; !ioctl( handle->fd, VIDIOC_ENUM_FMT, &v4l2_fmt ); v4l2_fmt.index++ )
  632.    {
  633.       int size_count;
  634.       unicap_rect_t *sizes;
  635.       char *identifier;
  636.       unsigned int fourcc;
  637.       int bpp;
  638.       char tmp_identifier[128];
  639.       
  640.       sprintf( tmp_identifier, "%s ( %c%c%c%c )", 
  641.        v4l2_fmt.description, 
  642.        ( v4l2_fmt.pixelformat & 0xff ), 
  643.        ( v4l2_fmt.pixelformat >> 8 & 0xff ), 
  644.        ( v4l2_fmt.pixelformat >> 16 & 0xff ), 
  645.        ( v4l2_fmt.pixelformat >> 24 & 0xff ) );
  646.       identifier = tmp_identifier;
  647.       bpp = v4l2_get_bpp( &v4l2_fmt );
  648.       fourcc = v4l2_fmt.pixelformat;
  649.       if( !handle->compat || ( handle->compat->fmt_get_func( &v4l2_fmt, &identifier, &fourcc, &bpp ) == STATUS_NO_MATCH ) )
  650.       {
  651.       }
  652.       sprintf( handle->unicap_formats[v4l2_fmt.index].identifier, identifier );
  653.       handle->unicap_formats[v4l2_fmt.index].bpp = bpp;
  654.       handle->unicap_formats[v4l2_fmt.index].fourcc = fourcc;
  655.       TRACE( "enum format: index %d desc %sn", v4l2_fmt.index, v4l2_fmt. description );
  656.       handle->unicap_formats[v4l2_fmt.index].size.width = v4l2_crop.defrect.width;
  657.       handle->unicap_formats[v4l2_fmt.index].size.height = v4l2_crop.defrect.height;
  658.       handle->unicap_formats[v4l2_fmt.index].buffer_type = UNICAP_BUFFER_TYPE_USER;
  659.       sizes = build_format_size_table( handle, v4l2_fmt.pixelformat, &size_count );
  660.       if( size_count == 0 )
  661.       {
  662.  handle->unicap_formats[v4l2_fmt.index].min_size.width = 
  663.     handle->unicap_formats[v4l2_fmt.index].min_size.height = 1;
  664.  handle->unicap_formats[v4l2_fmt.index].max_size.width = v4l2_crop.bounds.width;
  665.  handle->unicap_formats[v4l2_fmt.index].max_size.height = v4l2_crop.bounds.height;
  666.  if( v4l2_crop.defrect.width && v4l2_crop.defrect.height )
  667.  {
  668.     handle->unicap_formats[v4l2_fmt.index].buffer_size = 
  669.        v4l2_crop.defrect.width * v4l2_crop.defrect.height * handle->unicap_formats[v4l2_fmt.index].bpp / 8;
  670.  }
  671.  else
  672.  {
  673.     handle->unicap_formats[v4l2_fmt.index].buffer_size =
  674.        v4l2_crop.bounds.width * v4l2_crop.bounds.height * handle->unicap_formats[v4l2_fmt.index].bpp / 8;
  675.  }
  676.  
  677.  handle->unicap_formats[v4l2_fmt.index].h_stepping = 16;
  678.  handle->unicap_formats[v4l2_fmt.index].v_stepping = 16;
  679.  handle->unicap_formats[v4l2_fmt.index].sizes = 0;
  680.  handle->unicap_formats[v4l2_fmt.index].size_count = 0;
  681.       }
  682.       else
  683.       {
  684.  // TODO : fix: currently assuming smallest format is first;
  685.  // largest is last
  686.  handle->unicap_formats[v4l2_fmt.index].min_size.width = sizes[0].width;
  687.  handle->unicap_formats[v4l2_fmt.index].min_size.height = sizes[0].height;
  688.  handle->unicap_formats[v4l2_fmt.index].max_size.width = sizes[size_count-1].width;
  689.  handle->unicap_formats[v4l2_fmt.index].max_size.height = sizes[size_count-1].height;
  690.  handle->unicap_formats[v4l2_fmt.index].sizes = sizes;
  691.  handle->unicap_formats[v4l2_fmt.index].size_count = size_count;
  692.  handle->unicap_formats[v4l2_fmt.index].buffer_size = 
  693.     ( sizes[size_count-1].width * sizes[size_count-1].height * handle->unicap_formats[v4l2_fmt.index].bpp / 8 );
  694.       } 
  695.       v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  696.    }
  697.    handle->format_count = v4l2_fmt.index;
  698.    return STATUS_SUCCESS;
  699. }
  700. static unicap_status_t v4l2_enumerate_formats( void *cpi_data, unicap_format_t *format, int index )
  701. {
  702.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  703. /*  TRACE( "enumerate formats: %d (%d)n", index, handle->format_count ); */
  704.    if( index >= handle->format_count )
  705.    {
  706.       return STATUS_NO_MATCH;
  707.    }
  708.    unicap_copy_format( format, &handle->unicap_formats[index] );
  709.    return STATUS_SUCCESS;
  710. }
  711. static unicap_status_t v4l2_set_format( void *cpi_data, unicap_format_t *format )
  712. {
  713.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  714.    struct v4l2_format v4l2_fmt;
  715.    int i;
  716.    int index = -1;
  717.    __u32 fourcc;
  718.    TRACE( "v4l2_set_formatn" );
  719.    for( i = 0; i < handle->format_count; i++ )
  720.    {
  721.       if( !strcmp( format->identifier, handle->unicap_formats[ i ].identifier ) )
  722.       {
  723.  index = i;
  724.  break;
  725.       }
  726.    }
  727.    if( index == -1 )
  728.    {
  729.       TRACE( "v4l2_set_format failed: NO_MATCHn" );
  730.       return STATUS_NO_MATCH;
  731.    }
  732.    v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  733.    v4l2_fmt.fmt.pix.width = format->size.width;
  734.    v4l2_fmt.fmt.pix.height = format->size.height;
  735.    v4l2_fmt.fmt.pix.pixelformat = handle->unicap_formats[ index ].fourcc;
  736.    v4l2_fmt.fmt.pix.field = V4L2_FIELD_ANY;
  737.    fourcc = handle->unicap_formats[ index ].fourcc;
  738.    if( ioctl( handle->fd, VIDIOC_S_FMT, &v4l2_fmt ) < 0 )
  739.    {
  740.       TRACE( "VIDIOC_S_FMT ioctl failed: %sn", strerror( errno ) );
  741.       return STATUS_FAILURE;
  742.    }
  743.    unicap_copy_format( &handle->current_format, format );
  744.    handle->current_format.buffer_size = format->size.width * format->size.height * handle->unicap_formats[index].bpp / 8;
  745.    return STATUS_SUCCESS;
  746. }
  747. static unicap_status_t v4l2_get_format( void *cpi_data, unicap_format_t *format )
  748. {
  749.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  750.    unicap_copy_format( format, &handle->current_format );
  751.    return STATUS_SUCCESS;
  752. }
  753. static unicap_status_t v4l2_enum_frameintervals( v4l2_handle_t handle, unicap_property_t *property )
  754. {
  755. #ifdef VIDIOC_ENUM_FRAMEINTERVALS
  756.    unicap_format_t format;
  757.    struct v4l2_frmivalenum frmival;
  758.    
  759.    TRACE( "v4l2_enum_frameintervalsn" );
  760.    v4l2_get_format( handle, &format );
  761.    if( !format.fourcc )
  762.    {
  763.       return STATUS_FAILURE;
  764.    }
  765.    
  766.    frmival.pixel_format = format.fourcc;
  767.    frmival.width = format.size.width;
  768.    frmival.height = format.size.height;
  769.    handle->frame_rate_count = 0;
  770.                                                                                             
  771.    for( frmival.index = 0; 
  772. ( frmival.index < V4L2_MAX_FRAME_RATES ) && ( ioctl( handle->fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival ) >= 0 ); 
  773. frmival.index++ )
  774.    {
  775.       if( frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE )
  776.       {
  777.  handle->frame_rates[ frmival.index ] = 1/((double)frmival.discrete.numerator / (double)frmival.discrete.denominator);
  778.  TRACE( "num: %d denom: %dn", frmival.discrete.numerator, frmival.discrete.denominator );
  779.       }
  780.       else
  781.       {
  782.  handle->frame_rates[ frmival.index ] = 1/((double)frmival.stepwise.max.numerator / (double)frmival.stepwise.max.denominator);
  783.       }
  784.       handle->frame_rate_count++;
  785.    }
  786.    
  787.    if( frmival.index == 0 )
  788.    {
  789.       return STATUS_FAILURE;
  790.    }
  791.    
  792.    property->value_list.values = handle->frame_rates;
  793.    property->value_list.value_count = frmival.index;
  794.    strcpy( property->identifier, V4L2_VIDEO_FRAMERATE_PPTY_NAME );
  795.    strcpy( property->category, "video" );
  796.    strcpy( property->unit, "" );
  797.    property->relations = 0;
  798.    property->relations_count = 0;
  799.    property->value = property->value_list.values[0];
  800.    property->stepping = 0;
  801.    property->type = UNICAP_PROPERTY_TYPE_VALUE_LIST;
  802.    property->flags = UNICAP_FLAGS_MANUAL;
  803.    property->flags_mask = UNICAP_FLAGS_MANUAL;
  804.    property->property_data = 0;
  805.    property->property_data_size = 0;
  806.    return STATUS_SUCCESS;
  807. #else // ndef VIDIOC_ENUM_FRAMEINTERVALS
  808.    return STATUS_FAILURE;
  809. #endif
  810. }
  811. static unicap_status_t v4l2_set_frame_interval( v4l2_handle_t handle, unicap_property_t *property )
  812. {
  813. #ifdef VIDIOC_S_PARM
  814.    struct v4l2_streamparm parm;
  815.    
  816.    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  817.    parm.parm.capture.timeperframe.numerator = 100;
  818.    parm.parm.capture.timeperframe.denominator = property->value * 100;
  819.    
  820.    if( ioctl( handle->fd, VIDIOC_S_PARM, &parm ) < 0 )
  821.    {
  822.       TRACE( "Failed to set frame intervaln" );
  823.       return STATUS_FAILURE;
  824.    }
  825.    return STATUS_SUCCESS;   
  826. #else
  827.    return STATUS_FAILURE;
  828. #endif
  829. }
  830. static unicap_status_t v4l2_get_frame_interval( v4l2_handle_t handle, unicap_property_t *property )
  831. {
  832. #ifdef VIDIOC_G_PARM
  833.    struct v4l2_streamparm parm;
  834.    
  835.    parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  836.    
  837.    if( ioctl( handle->fd, VIDIOC_G_PARM, &parm ) < 0 )
  838.    {
  839.       TRACE( "Failed to get frame intervaln" );
  840.       return STATUS_FAILURE;
  841.    }
  842.    
  843.    property->value = 1/( (double)parm.parm.capture.timeperframe.numerator / (double) parm.parm.capture.timeperframe.denominator );
  844.    
  845.    return STATUS_SUCCESS;
  846. #else
  847.    return STATUS_FAILURE;
  848. #endif
  849. }
  850. static unicap_status_t v4l2_enum_inputs( v4l2_handle_t handle, unicap_property_t *property )
  851. {
  852.    struct v4l2_input input;
  853.    for( input.index = 0; 
  854. (input.index < V4L2_MAX_VIDEO_INPUTS ) && 
  855.    ( ioctl( handle->fd, VIDIOC_ENUMINPUT, &input ) == 0 ); 
  856. input.index++ )
  857.    {
  858.       strncpy( handle->video_inputs[input.index], (char*)input.name, 32 );
  859.    }
  860.    // Only present inputs if there are more than one
  861.    if( input.index <= 1 )
  862.    {
  863.       return STATUS_FAILURE;
  864.    }
  865.    property->menu.menu_items = handle->video_inputs;
  866.    property->menu.menu_item_count = input.index;
  867.    strcpy( property->identifier, V4L2_VIDEO_IN_PPTY_NAME );
  868.    strcpy( property->category, N_("source") );
  869.    strcpy( property->unit, "" );
  870.    property->relations = 0;
  871.    property->relations_count = 0;
  872.    strcpy( property->menu_item, property->menu.menu_items[0] );
  873.    property->stepping = 0;
  874.    property->type = UNICAP_PROPERTY_TYPE_MENU;
  875.    property->flags = UNICAP_FLAGS_MANUAL;
  876.    property->flags_mask = UNICAP_FLAGS_MANUAL;
  877.    property->property_data = 0;
  878.    property->property_data_size = 0;
  879.    handle->video_in_count = input.index;
  880.    return STATUS_SUCCESS;
  881. }
  882. static unicap_status_t v4l2_enum_norms( v4l2_handle_t handle, unicap_property_t *property )
  883. {
  884.    struct v4l2_input input;
  885.    struct v4l2_standard standard;
  886.    
  887.    if( ioctl( handle->fd, VIDIOC_G_INPUT, &input.index ) < 0 ) 
  888.    {
  889.       TRACE( "Failed to get inputn" );
  890.       return STATUS_FAILURE;
  891.    }
  892.    input.index = 0;
  893.    
  894.    if( ioctl( handle->fd, VIDIOC_ENUMINPUT, &input ) < 0 ) 
  895.    {
  896.       TRACE( "Failed to enumerate inputn" );
  897.       return STATUS_FAILURE;
  898.    }
  899.    
  900.    standard.index = 0;
  901.    
  902.    while( ioctl( handle->fd, VIDIOC_ENUMSTD, &standard ) == 0 ) 
  903.    {
  904.       if( standard.id && input.std )
  905.       {
  906.  TRACE ("Found norm: %sn", standard.name);
  907.  strcpy( handle->video_norms[standard.index], (char*)standard.name );
  908.       }
  909.       standard.index++;
  910.    }
  911.    /* From v4l2-draft:
  912.       EINVAL indicates the end of the enumeration, which cannot be
  913.       empty unless this device falls under the USB exception. */
  914.    if( errno != EINVAL || standard.index == 0 ) 
  915.    {
  916.       TRACE( "Failed to enumerate normsn" );
  917.       return STATUS_FAILURE;
  918.    }
  919.    property->menu.menu_items = (char**)handle->video_norms;
  920.    property->menu.menu_item_count = standard.index;
  921.    strcpy( property->identifier, V4L2_VIDEO_NORM_PPTY_NAME );
  922.    strcpy( property->category, "source" );
  923.    strcpy( property->unit, "" );
  924.    property->relations = 0;
  925.    property->relations_count = 0;
  926.    strcpy( property->menu_item, property->menu.menu_items[0] );
  927.    property->stepping = 0;
  928.    property->type = UNICAP_PROPERTY_TYPE_MENU;
  929.    property->flags = UNICAP_FLAGS_MANUAL;
  930.    property->flags_mask = UNICAP_FLAGS_MANUAL;
  931.    property->property_data = 0;
  932.    property->property_data_size = 0;
  933.    
  934.    TRACE( "-enum_normsn" );
  935.    return STATUS_SUCCESS;
  936. }
  937. static unicap_status_t v4l2_reenumerate_properties( void *cpi_data, int *_pcount )
  938. {
  939.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  940.    struct v4l2_queryctrl v4l2ctrl;
  941.    int count = 0;
  942.    int compat_count = 0;
  943.    int index = 0;
  944.    int ppty_index = 0;
  945.    int res;
  946.    TRACE( "v4l2_reenumerate_propertiesn" );
  947.    if( handle->unicap_properties )
  948.    {
  949.       free( handle->unicap_properties );
  950.       handle->unicap_properties = 0;
  951.    }
  952.    if( handle->control_ids )
  953.    {
  954.       free( handle->control_ids );
  955.       handle->control_ids = 0;
  956.    }
  957.    for( index = V4L2_CID_BASE; index < V4L2_CID_LASTP1; index++ )
  958.    {
  959.       v4l2ctrl.id = index;
  960.       if( ioctl( handle->fd, VIDIOC_QUERYCTRL, &v4l2ctrl ) )
  961.       {
  962.  if( errno == EINVAL )
  963.  {
  964.     continue;
  965.  }
  966.  TRACE( "ioctl failed at index: %dn", index );
  967.  perror( "error" );
  968.  continue;
  969.       }
  970.       if( handle->compat && !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  971.       {
  972.  if( handle->compat->override_property_func )
  973.  {
  974.     unicap_status_t status = handle->compat->override_property_func( handle->fd, &v4l2ctrl, NULL );
  975.     if( status == STATUS_SUCCESS )
  976.     {
  977.        count++;
  978.        continue;
  979.     }
  980.     else if( status == STATUS_SKIP_CTRL )
  981.     {
  982.        continue;
  983.     }
  984.  }
  985.       }      
  986.       if( !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  987.       {
  988.  count++;
  989.       }
  990.    }
  991.    for( index = V4L2_CID_PRIVATE_BASE; index < ( V4L2_CID_PRIVATE_BASE + 1000 ); index++ )
  992.    {
  993.       v4l2ctrl.id = index;
  994.       if( ioctl( handle->fd, VIDIOC_QUERYCTRL, &v4l2ctrl ) )
  995.       {
  996.  if( errno == EINVAL )
  997.  {
  998.     continue;
  999.  }
  1000.  TRACE( "ioctl failed at index: %dn", index );
  1001.  perror( "error" );
  1002.  return STATUS_FAILURE;
  1003.       }
  1004.       if( handle->compat && !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1005.       {
  1006.  if( handle->compat->override_property_func )
  1007.  {
  1008.     unicap_status_t status = handle->compat->override_property_func( handle->fd, &v4l2ctrl, NULL );
  1009.     if( status == STATUS_SUCCESS )
  1010.     {
  1011.        count++;
  1012.        continue;
  1013.     }
  1014.     else if( status == STATUS_SKIP_CTRL )
  1015.     {
  1016.        continue;
  1017.     }
  1018.  }
  1019.       }      
  1020.       if( !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1021.       {
  1022.  count++;
  1023.       }
  1024.    }
  1025.    
  1026.    count++;// video input source property
  1027.    count++;// video norm property
  1028.    count++;// frame rate property
  1029.    if( handle->compat )
  1030.    {
  1031.       compat_count = handle->compat->count_ext_property_func( handle->fd );
  1032.       count += compat_count;
  1033.    }
  1034.    handle->unicap_properties = (unicap_property_t *) malloc( count * sizeof( unicap_property_t ) );
  1035.    handle->control_ids = (__u32*) malloc( count * sizeof( __u32 ) );
  1036.    handle->property_count = count;
  1037.    for( index = V4L2_CID_BASE; index < V4L2_CID_LASTP1; index++ )
  1038.    {
  1039.       v4l2ctrl.id = index;
  1040.       if( ioctl( handle->fd, VIDIOC_QUERYCTRL, &v4l2ctrl ) )
  1041.       {
  1042.  if( errno == EINVAL )
  1043.  {
  1044.     continue;
  1045.  }
  1046.  TRACE( "ioctl failedn" );
  1047.  perror( "error" );
  1048.  return STATUS_FAILURE;
  1049.       }
  1050.       if( handle->compat && !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1051.       {
  1052.  if( handle->compat->override_property_func )
  1053.  {
  1054.     unicap_status_t status = handle->compat->override_property_func( handle->fd, &v4l2ctrl, &handle->unicap_properties[ ppty_index ] );
  1055.     if( status == STATUS_SUCCESS )
  1056.     {
  1057.        ppty_index++;
  1058.        continue;
  1059.     }
  1060.     if( status == STATUS_SKIP_CTRL )
  1061.     {
  1062.        continue;
  1063.     }
  1064.  }
  1065.       }      
  1066.       if( !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1067.       {
  1068.  TRACE( "add property: %sn", v4l2ctrl.name );
  1069.  strcpy( handle->unicap_properties[ ppty_index ].identifier, 
  1070.  (char*)v4l2ctrl.name );
  1071.  handle->unicap_properties[ ppty_index ].value = v4l2ctrl.default_value;
  1072.  handle->unicap_properties[ ppty_index ].range.min = v4l2ctrl.minimum;
  1073.  handle->unicap_properties[ ppty_index ].range.max = v4l2ctrl.maximum;
  1074.  handle->unicap_properties[ ppty_index ].stepping = v4l2ctrl.step;
  1075.  handle->unicap_properties[ ppty_index ].type = UNICAP_PROPERTY_TYPE_RANGE;
  1076.  strcpy( handle->unicap_properties[ ppty_index ].category, N_("video") );
  1077.  strcpy( handle->unicap_properties[ ppty_index ].unit, "" );
  1078.  handle->unicap_properties[ ppty_index ].relations = 0;
  1079.  handle->unicap_properties[ ppty_index ].relations_count = 0;
  1080.  handle->unicap_properties[ ppty_index ].flags = UNICAP_FLAGS_MANUAL;
  1081.  handle->unicap_properties[ ppty_index ].flags_mask = UNICAP_FLAGS_MANUAL;
  1082.  handle->unicap_properties[ ppty_index ].property_data = 0;
  1083.  handle->unicap_properties[ ppty_index ].property_data_size = 0;
  1084.    
  1085.  handle->control_ids[ ppty_index ] = index;
  1086.    
  1087.  ppty_index++;
  1088.       }
  1089.    }
  1090.    for( index = V4L2_CID_PRIVATE_BASE; index < ( V4L2_CID_PRIVATE_BASE + 1000 ); index++ )
  1091.    {
  1092.       v4l2ctrl.id = index;
  1093.       if( ioctl( handle->fd, VIDIOC_QUERYCTRL, &v4l2ctrl ) )
  1094.       {
  1095.  if( errno == EINVAL )
  1096.  {
  1097.     continue;
  1098.  }
  1099.  TRACE( "ioctl failedn" );
  1100.  perror( "error" );
  1101.  return STATUS_FAILURE;
  1102.       }
  1103.       if( handle->compat && !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1104.       {
  1105.  if( handle->compat->override_property_func )
  1106.  {
  1107.     unicap_status_t status = handle->compat->override_property_func( handle->fd, &v4l2ctrl, &handle->unicap_properties[ ppty_index ] );
  1108.     if( status == STATUS_SUCCESS )
  1109.     {
  1110.        ppty_index++;
  1111.        continue;
  1112.     }
  1113.     if( status == STATUS_SKIP_CTRL )
  1114.     {
  1115.        continue;
  1116.     }
  1117.     
  1118.  }
  1119.       }      
  1120.       if( !v4l2ctrl.flags & V4L2_CTRL_FLAG_DISABLED )
  1121.       {
  1122.  TRACE( "add property: %sn", v4l2ctrl.name );
  1123.  strcpy( handle->unicap_properties[ ppty_index ].identifier, 
  1124.  (char*)v4l2ctrl.name );
  1125.  handle->unicap_properties[ ppty_index ].value = v4l2ctrl.default_value;
  1126.  handle->unicap_properties[ ppty_index ].range.min = v4l2ctrl.minimum;
  1127.  handle->unicap_properties[ ppty_index ].range.max = v4l2ctrl.maximum;
  1128.  handle->unicap_properties[ ppty_index ].stepping = v4l2ctrl.step;
  1129.  handle->unicap_properties[ ppty_index ].type = UNICAP_PROPERTY_TYPE_RANGE;
  1130.  strcpy( handle->unicap_properties[ ppty_index ].category, N_("extended") );
  1131.  strcpy( handle->unicap_properties[ ppty_index ].unit, "" );
  1132.  handle->unicap_properties[ ppty_index ].relations = 0;
  1133.  handle->unicap_properties[ ppty_index ].relations_count = 0;
  1134.  handle->unicap_properties[ ppty_index ].flags = UNICAP_FLAGS_MANUAL;
  1135.  handle->unicap_properties[ ppty_index ].flags_mask = UNICAP_FLAGS_MANUAL;
  1136.  handle->unicap_properties[ ppty_index ].property_data = 0;
  1137.  handle->unicap_properties[ ppty_index ].property_data_size = 0;
  1138.    
  1139.  handle->control_ids[ ppty_index ] = index;
  1140.    
  1141.  ppty_index++;
  1142.       }
  1143.    }
  1144.    if( !SUCCESS( v4l2_enum_inputs( handle, &handle->unicap_properties[ ppty_index++ ] ) ) )
  1145.    {
  1146.       handle->property_count--;
  1147.       ppty_index--;
  1148.    }
  1149.    
  1150.    if( !SUCCESS( v4l2_enum_norms( handle, &handle->unicap_properties[ ppty_index++ ] ) ) )
  1151.    {
  1152.       handle->property_count--;
  1153.       ppty_index--;
  1154.    }    
  1155.    if( !SUCCESS( v4l2_enum_frameintervals( handle, &handle->unicap_properties[ ppty_index++ ] ) ) )
  1156.    {
  1157.       handle->property_count--;
  1158.       ppty_index--;
  1159.    }
  1160.    if( handle->compat )
  1161.    {
  1162.       for( index = 0; index < compat_count; index++ )
  1163.       {
  1164.  if( !SUCCESS( handle->compat->enumerate_property_func( handle->fd, index, &handle->unicap_properties[ ppty_index++ ] ) ) )
  1165.  {
  1166.     handle->property_count--;
  1167.     ppty_index--;
  1168.  }
  1169.       }  
  1170.    }
  1171.    
  1172.       
  1173.    if( _pcount )
  1174.    {
  1175.       *_pcount = ppty_index;
  1176.    }
  1177.    return STATUS_SUCCESS;
  1178. }
  1179. static unicap_status_t v4l2_enumerate_properties( void *cpi_data, 
  1180.   unicap_property_t *property, int index )
  1181. {
  1182.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1183.    if( index >= handle->property_count )
  1184.    {
  1185.       return STATUS_NO_MATCH;
  1186.    }
  1187.    unicap_copy_property( property, &handle->unicap_properties[index] );
  1188.    return STATUS_SUCCESS;
  1189. }
  1190. static unicap_status_t v4l2_set_input( v4l2_handle_t handle, unicap_property_t *property )
  1191. {
  1192.    struct v4l2_input input;
  1193.    for( input.index = 0; input.index < handle->video_in_count; input.index++ )
  1194.    {
  1195.       if( !strcmp( property->menu_item, handle->video_inputs[input.index] ) )
  1196.       {
  1197.  if( ioctl( handle->fd, VIDIOC_S_INPUT, &input ) == 0 )
  1198.  {
  1199.     return STATUS_SUCCESS;
  1200.  }
  1201.  else
  1202.  {
  1203.     return STATUS_FAILURE;
  1204.  }
  1205.       }
  1206.    }
  1207.    return STATUS_NO_MATCH;
  1208. }
  1209. static unicap_status_t v4l2_set_norm( v4l2_handle_t handle, unicap_property_t *property )
  1210. {
  1211.    struct v4l2_input input;
  1212.    struct v4l2_standard standard;
  1213.    v4l2_std_id id=0;
  1214.    
  1215.    if( ioctl( handle->fd, VIDIOC_G_INPUT, &input.index ) < 0 ) 
  1216.    {
  1217.       TRACE( "Failed to get inputn" );
  1218.       return STATUS_FAILURE;
  1219.    }
  1220.    input.index = 0;
  1221.    
  1222.    if( ioctl( handle->fd, VIDIOC_ENUMINPUT, &input ) < 0 ) 
  1223.    {
  1224.       TRACE( "Failed to enumerate inputn" );
  1225.       return STATUS_FAILURE;
  1226.    }
  1227.    
  1228.    standard.index = 0;
  1229.    
  1230.    while( ioctl( handle->fd, VIDIOC_ENUMSTD, &standard ) == 0 ) 
  1231.    {
  1232.       if( standard.id & input.std )
  1233.       {
  1234.  TRACE ("Found norm: %s [%016llx], looking for: %sn", 
  1235. standard.name, standard.id, property->menu_item);
  1236.  if( !strcmp( property->menu_item, (char*)standard.name ) )
  1237.  {
  1238.     id = standard.id;
  1239.     break;
  1240.  }
  1241.       }
  1242.       standard.index++;
  1243.    }
  1244.    TRACE( "Set norm: %016llxn", id );
  1245.    if( ioctl( handle->fd, VIDIOC_S_STD, &id ) < 0 )
  1246.    {
  1247.       TRACE( "Failed to set norm: %016llx %016llxn", id, input.std );
  1248.       return STATUS_FAILURE;
  1249.    }
  1250.    return STATUS_SUCCESS;
  1251. }
  1252. static unicap_status_t v4l2_set_property( void *cpi_data, unicap_property_t *property )
  1253. {
  1254.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1255.    unicap_status_t status;
  1256.    int index;
  1257.    TRACE( "v4l2_set_propertyn" );
  1258.    if( handle->compat )
  1259.    {
  1260.       status = handle->compat->set_property_func( handle->fd, property );
  1261.       if( status != STATUS_NO_MATCH )
  1262.       {
  1263.  return status;
  1264.       }
  1265.    }
  1266.    if( !strcmp( property->identifier, V4L2_VIDEO_IN_PPTY_NAME ) )
  1267.    {
  1268.       return v4l2_set_input( handle, property );
  1269.    }
  1270.    
  1271.    if( !strcmp( property->identifier, V4L2_VIDEO_NORM_PPTY_NAME ) )
  1272.    {
  1273.       return v4l2_set_norm( handle, property );
  1274.    }
  1275.    if( !strcmp( property->identifier, V4L2_VIDEO_FRAMERATE_PPTY_NAME ) )
  1276.    {
  1277.       return v4l2_set_frame_interval( handle, property );
  1278.    }
  1279.    for( index = 0; index < handle->property_count; index++ )
  1280.    {
  1281.       
  1282.       if( !strcmp( property->identifier, handle->unicap_properties[index].identifier ) )
  1283.       {
  1284.  struct v4l2_control v4l2ctrl;
  1285.  v4l2ctrl.id = handle->control_ids[ index ];
  1286.  v4l2ctrl.value = property->value;
  1287.  if( ioctl( handle->fd, VIDIOC_S_CTRL, &v4l2ctrl ) < 0 )
  1288.  {
  1289.     TRACE( "VIDIOC_S_CTRL failedn" );
  1290.     return STATUS_FAILURE;
  1291.  }
  1292.  return STATUS_SUCCESS;
  1293.       }
  1294.    }
  1295.    return STATUS_NO_MATCH;
  1296. }
  1297. static unicap_status_t v4l2_get_input( v4l2_handle_t handle, unicap_property_t *property )
  1298. {
  1299.    struct v4l2_input input;
  1300.    if( !ioctl( handle->fd, VIDIOC_G_INPUT, &input ) )
  1301.    {
  1302.       strcpy( property->menu_item, handle->video_inputs[input.index] );
  1303.       return STATUS_SUCCESS;
  1304.    }
  1305.    return STATUS_FAILURE;
  1306. }
  1307. static unicap_status_t v4l2_get_norm( v4l2_handle_t handle, unicap_property_t *property )
  1308. {
  1309.    struct v4l2_standard standard;
  1310.    v4l2_std_id id=0;
  1311.    unicap_status_t status = STATUS_FAILURE;
  1312.    
  1313.    if( ioctl( handle->fd, VIDIOC_G_STD, &id ) < 0 ) 
  1314.    {
  1315.       TRACE( "Failed to get normn" );
  1316.       return STATUS_FAILURE;
  1317.    }
  1318.    standard.index = 0;
  1319.    
  1320.    while( ioctl( handle->fd, VIDIOC_ENUMSTD, &standard ) == 0 ) 
  1321.    {
  1322.       if( standard.id & id )
  1323.       {
  1324.  TRACE ("Found norm: %s [%016llx]", 
  1325. standard.name, standard.id );
  1326.  strcpy( property->menu_item, (char*)standard.name );
  1327.  status = STATUS_SUCCESS;
  1328.  break;
  1329.       }
  1330.       standard.index++;
  1331.    }
  1332.    return status;
  1333. }
  1334. static unicap_status_t v4l2_get_property( void *cpi_data, unicap_property_t *property )
  1335. {
  1336.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1337.    unicap_status_t status;
  1338.    int index;
  1339. /*    TRACE( "v4l2_get_propertyn" ); */
  1340.    
  1341.    
  1342.    for( index = 0; index < handle->property_count; index++ )
  1343.    {
  1344.       if( !strcmp( property->identifier, handle->unicap_properties[index].identifier ) )
  1345.       {
  1346.  struct v4l2_control v4l2ctrl;
  1347.  unicap_copy_property( property, &handle->unicap_properties[ index ] );
  1348.  if( handle->compat )
  1349.  {
  1350.     status = handle->compat->get_property_func( handle->fd, property );
  1351.     if( status != STATUS_NO_MATCH )
  1352.     {
  1353.        return status;
  1354.     }   
  1355.  }
  1356.  if( !strcmp( property->identifier, V4L2_VIDEO_IN_PPTY_NAME ) )
  1357.  {
  1358.     return v4l2_get_input( handle, property );
  1359.  }
  1360.  if( !strcmp( property->identifier, V4L2_VIDEO_NORM_PPTY_NAME ) )
  1361.  {
  1362.     return v4l2_get_norm( handle, property );
  1363.  }
  1364.  if( !strcmp( property->identifier, V4L2_VIDEO_FRAMERATE_PPTY_NAME ) )
  1365.  {
  1366.     return v4l2_get_frame_interval( handle, property );
  1367.  }
  1368.  v4l2ctrl.id = handle->control_ids[ index ];
  1369.  if( ioctl( handle->fd, VIDIOC_G_CTRL, &v4l2ctrl ) < 0 )
  1370.  {
  1371.     TRACE( "VIDIOC_G_CTRL failedn" );
  1372.     return STATUS_FAILURE;
  1373.  }
  1374.  property->value = v4l2ctrl.value;
  1375.  return STATUS_SUCCESS;
  1376.       }
  1377.    }
  1378.    return STATUS_NO_MATCH;
  1379. }
  1380. static unicap_status_t v4l2_capture_start( void *cpi_data )
  1381. {
  1382.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1383.    struct v4l2_requestbuffers v4l2_reqbuf;
  1384. /*  int v4l2_argp; */
  1385.    TRACE( "v4l2_start_capturen" );
  1386.    if( handle->capture_running )
  1387.    {
  1388.       return STATUS_CAPTURE_ALREADY_STARTED;
  1389.    }
  1390.    
  1391.    memset( &v4l2_reqbuf, 0x0, sizeof( struct v4l2_requestbuffers ) );
  1392.    handle->qindex = 0;
  1393.    v4l2_reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1394.    switch( handle->io_method )
  1395.    {
  1396.       case CPI_V4L2_IO_METHOD_MMAP:
  1397.       {
  1398.  v4l2_reqbuf.memory = V4L2_MEMORY_MMAP;
  1399.  v4l2_reqbuf.count = handle->buffer_count;
  1400.  handle->buffers = calloc( v4l2_reqbuf.count, sizeof( struct _cpi_v4l2_buffer ) );
  1401.  if( !handle->buffers )
  1402.  {
  1403.     TRACE( "calloc failedn" );
  1404.     return STATUS_FAILURE;
  1405.  }
  1406.  handle->free_buffers = calloc( v4l2_reqbuf.count, sizeof( int ) );
  1407.  if( !handle->free_buffers )
  1408.  {
  1409.     free( handle->buffers );
  1410.     TRACE( "calloc failedn" );
  1411.     return STATUS_FAILURE;
  1412.  }
  1413.  memset( handle->free_buffers, 0x0, sizeof( int ) * v4l2_reqbuf.count );
  1414.  TRACE( "Method: MMAPn" );
  1415.       }
  1416.       break;
  1417.       case CPI_V4L2_IO_METHOD_USERPOINTER:
  1418.  v4l2_reqbuf.memory = V4L2_MEMORY_USERPTR;
  1419.  TRACE( "Method: USERPOINTERn" );
  1420.  break;
  1421.       default:
  1422. /*  ERROR( "Unknown IO method! Capture can not start!n" ); */
  1423.  return STATUS_FAILURE;
  1424.    }
  1425.    if( ioctl( handle->fd, VIDIOC_REQBUFS, &v4l2_reqbuf ) < 0 )
  1426.    {
  1427.       TRACE( "VIDIOC_REQBUFS failed: %sn", strerror( errno ) );
  1428.       return STATUS_FAILURE;
  1429.    }
  1430.    if( handle->io_method == CPI_V4L2_IO_METHOD_MMAP )
  1431.    {
  1432.       int i;
  1433.       int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1434.       // method mmap returns the number of actual allocated buffers
  1435.       handle->buffer_count = v4l2_reqbuf.count;
  1436.       if( !handle->buffer_count )
  1437.       {
  1438.  TRACE( "buffer_count == 0n" );
  1439.  return STATUS_FAILURE;
  1440.       }
  1441.       for( i = 0; i < handle->buffer_count; i++ )
  1442.       {
  1443.  struct v4l2_buffer v4l2_buffer;
  1444.  v4l2_buffer.type = v4l2_reqbuf.type;
  1445.  v4l2_buffer.memory = V4L2_MEMORY_MMAP;
  1446.  v4l2_buffer.index = i;
  1447.  if( ioctl( handle->fd, VIDIOC_QUERYBUF, &v4l2_buffer ) < 0 )
  1448.  {
  1449.     TRACE( "VIDIOC_QUERYBUF ioctl failed: %s, index = %dn", strerror( errno ), i );
  1450.     free( handle->buffers );
  1451.     free( handle->free_buffers );
  1452.     return STATUS_FAILURE;
  1453.  }
  1454.  handle->buffers[i].length = v4l2_buffer.length;
  1455.  handle->buffers[i].start = mmap( NULL, v4l2_buffer.length,
  1456.   PROT_READ | PROT_WRITE, /* required */
  1457.   MAP_SHARED,             /* recommended */
  1458.   handle->fd, v4l2_buffer.m.offset);
  1459.  if( handle->buffers[i].start == MAP_FAILED )
  1460.  {
  1461.     int j;
  1462.     TRACE( "mmap failedn" );
  1463.     for( j = 0; j < i; j++ )
  1464.     {
  1465.        munmap( handle->buffers[i].start, handle->buffers[i].length );
  1466.     }
  1467.     free( handle->buffers );
  1468.     free( handle->free_buffers );
  1469.     return STATUS_FAILURE;
  1470.  }
  1471.  handle->free_buffers[i] = 1;
  1472.       }
  1473.       if( ioctl( handle->fd, VIDIOC_STREAMON, &type ) < 0 )
  1474.       {
  1475.  int j;
  1476.  TRACE( "VIDIOC_STREAMON ioctl failed: %sn", strerror( errno ) );
  1477.  for( j = 0; j < i; j++ )
  1478.  {
  1479.     munmap( handle->buffers[i].start, handle->buffers[i].length );
  1480.  }
  1481.  free( handle->buffers );
  1482.  free( handle->free_buffers );
  1483.  return STATUS_FAILURE;
  1484.       }
  1485.    }
  1486. /*    v4l2_get_format( cpi_data, &handle->current_format ); */
  1487.    handle->capture_running = 1;
  1488.    if( _queue_get_size( handle->in_queue ) )
  1489.    {
  1490.       int i, size;
  1491.       size = _queue_get_size( handle->in_queue );
  1492.       
  1493.       for( i = 0; i < size; i++ )
  1494.       {
  1495.  unicap_data_buffer_t *buffer;
  1496.  struct _unicap_queue *entry;
  1497.  
  1498.  entry = _get_front_queue( handle->in_queue );
  1499.  buffer = ( unicap_data_buffer_t * ) entry->data;
  1500.  queue_buffer( handle, buffer );
  1501.       }
  1502.    }
  1503.    if( handle->current_format.buffer_type == UNICAP_BUFFER_TYPE_SYSTEM )
  1504.    {
  1505.       queue_system_buffers( handle );
  1506.    }
  1507.    handle->quit_capture_thread = 0;
  1508.    pthread_create( &handle->capture_thread, NULL, (void*(*)(void*))v4l2_capture_thread, handle );
  1509.  
  1510.    return STATUS_SUCCESS;
  1511. }
  1512. static unicap_status_t v4l2_capture_stop( void *cpi_data )
  1513. {
  1514.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1515.    
  1516.    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1517.    int i;
  1518.    if( handle->capture_running )
  1519.    {
  1520.       handle->capture_running = 0;
  1521.       handle->quit_capture_thread = 1;
  1522.       pthread_join( handle->capture_thread, NULL );
  1523.       if( ioctl( handle->fd, VIDIOC_STREAMOFF, &type ) < 0  )
  1524.       {
  1525.  TRACE( "VIDIOC_STREAMOFF ioctl failed: %sn", strerror( errno ) );
  1526.  return STATUS_FAILURE;
  1527.       }
  1528.       
  1529.       while( _get_front_queue( handle->in_queue ) )
  1530.       {
  1531.  TRACE( "!!possible memleakn" );
  1532.       }
  1533.       for( i = 0; i < handle->buffer_count; i++ )
  1534.       {
  1535.  munmap( handle->buffers[i].start, handle->buffers[i].length );
  1536.       }
  1537.       free( handle->buffers );
  1538.       free( handle->free_buffers );
  1539.    }
  1540.    
  1541.    return STATUS_SUCCESS;
  1542. }
  1543. static unicap_status_t queue_buffer( v4l2_handle_t handle, unicap_data_buffer_t *buffer )
  1544. {
  1545.    struct v4l2_buffer v4l2_buffer;
  1546.    
  1547.    v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1548.    v4l2_buffer.length = buffer->buffer_size;
  1549.    switch( handle->io_method )
  1550.    {
  1551.       case CPI_V4L2_IO_METHOD_MMAP:
  1552.       {
  1553.  int index = -1;
  1554.  struct v4l2_buffer v4l2_buffer;
  1555.  int i;
  1556.  v4l2_buffer.index = 0;
  1557.  v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1558.  v4l2_buffer.memory = V4L2_MEMORY_MMAP;
  1559. /*   for( i = 0; i < handle->buffer_count; i++ ) */
  1560. /*   { */
  1561. /*      v4l2_buffer.index = i; */
  1562. /*      v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; */
  1563. /*      // TODO: Check correct way to do this */
  1564. /*      if( ioctl( handle->fd, VIDIOC_QUERYBUF, &v4l2_buffer ) ) */
  1565. /*      { */
  1566. /*         TRACE( "VIDIOC_QUERYBUF ioctl failed: %sn", strerror( errno ) ); */
  1567. /*         TRACE( "index = %dn", v4l2_buffer.index  ); */
  1568. /*         index = i; */
  1569. /*         break; */
  1570. /*      } */
  1571. /*      if( !(v4l2_buffer.flags & V4L2_BUF_FLAG_QUEUED ) && !( v4l2_buffer.flags & V4L2_BUF_FLAG_DONE ) ) */
  1572. /*      { */
  1573. /*         index = i; */
  1574. /*         break; */
  1575. /*      } */
  1576. /*   } */
  1577.  if( sem_wait( &handle->sema ) )
  1578.  {
  1579.     TRACE( "SEM_WAIT FAILED!n" );
  1580.     return STATUS_FAILURE;
  1581.  }
  1582.  if( ( ( handle->qindex + 1 ) % handle->buffer_count ) == handle->dqindex )
  1583.  {
  1584.     TRACE( "NO BUFFERSn" );
  1585.     sem_post( &handle->sema );
  1586.     return STATUS_NO_BUFFERS;
  1587.  }
  1588.  v4l2_buffer.index = handle->qindex;
  1589.  buffer->reserved[0] = handle->qindex;
  1590.  TRACE( "Q: index = %d type = %u, memory = %un", handle->qindex, v4l2_buffer.type, v4l2_buffer.memory );
  1591.  handle->qindex = ( handle->qindex + 1 ) % handle->buffer_count;
  1592.  v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1593.  if( ioctl( handle->fd, VIDIOC_QBUF, &v4l2_buffer ) < 0 )
  1594.  {
  1595.     TRACE( "VIDIOC_QBUF ioctl failed: %sn", strerror( errno ) );
  1596.     sem_post( &handle->sema );
  1597.     return STATUS_FAILURE;
  1598.  }
  1599.  if( sem_post( &handle->sema ) )
  1600.  {
  1601.     TRACE( "SEM_POST FAILEDn" );
  1602.     return STATUS_FAILURE;
  1603.  }  
  1604.       }
  1605.       break;
  1606.       case CPI_V4L2_IO_METHOD_USERPOINTER:
  1607.       {
  1608.  v4l2_buffer.m.userptr = ( unsigned long ) buffer->data;
  1609.  v4l2_buffer.memory = V4L2_MEMORY_USERPTR;
  1610.  v4l2_buffer.index = 0;
  1611.  if( ioctl( handle->fd, VIDIOC_QBUF, &v4l2_buffer ) < 0 )
  1612.  {
  1613.     TRACE( "VIDIOC_QBUF ioctl failed: %sn", strerror( errno ) );
  1614.     return STATUS_FAILURE;
  1615.  }
  1616.  if( _queue_get_size( handle->in_queue ) == 2 )
  1617.  {
  1618.     int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1619.     if( ioctl( handle->fd, VIDIOC_STREAMON, &type ) < 0 )
  1620.     {
  1621.        TRACE( "VIDIOC_STREAMON ioctl failed: %sn", strerror( errno ) );
  1622.        return STATUS_FAILURE;
  1623.     }
  1624.     TRACE( "streamonn" );
  1625.  }
  1626.       }
  1627.       break;
  1628.       default:
  1629.  return STATUS_FAILURE;
  1630.    }
  1631.    return STATUS_SUCCESS;
  1632. }
  1633. static unicap_status_t queue_system_buffers( v4l2_handle_t handle )
  1634. {
  1635.    struct v4l2_buffer v4l2_buffer;
  1636.    
  1637.    v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1638.    v4l2_buffer.length = handle->current_format.buffer_size;
  1639.    switch( handle->io_method )
  1640.    {
  1641.       case CPI_V4L2_IO_METHOD_MMAP:
  1642.       {
  1643.  int index = -1;
  1644.  struct v4l2_buffer v4l2_buffer;
  1645.  int i;
  1646.  v4l2_buffer.index = 0;
  1647.  v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1648.  v4l2_buffer.memory = V4L2_MEMORY_MMAP;
  1649.  if( sem_wait( &handle->sema ) )
  1650.  {
  1651.     TRACE( "SEM_WAIT FAILED!n" );
  1652.     return STATUS_FAILURE;
  1653.  }
  1654.  for( i = 0; i < handle->buffer_count; i++ )
  1655.  {
  1656.     if( ( ( handle->qindex + 1 ) % handle->buffer_count ) == handle->dqindex )
  1657.     {
  1658.        TRACE( "NO BUFFERSn" );
  1659.        sem_post( &handle->sema );
  1660.        return STATUS_NO_BUFFERS;
  1661.     }
  1662.     v4l2_buffer.index = handle->qindex;
  1663.     TRACE( "Q: index = %d type = %u, memory = %un", handle->qindex, v4l2_buffer.type, v4l2_buffer.memory );
  1664.     handle->qindex = ( handle->qindex + 1 ) % handle->buffer_count;
  1665.     v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1666.     if( ioctl( handle->fd, VIDIOC_QBUF, &v4l2_buffer ) < 0 )
  1667.     {
  1668.        TRACE( "VIDIOC_QBUF ioctl failed: %sn", strerror( errno ) );
  1669.        sem_post( &handle->sema );
  1670.        return STATUS_FAILURE;
  1671.     }
  1672.     if( sem_post( &handle->sema ) )
  1673.     {
  1674.        TRACE( "SEM_POST FAILEDn" );
  1675.        return STATUS_FAILURE;
  1676.     }  
  1677.  }
  1678.       }
  1679.       break;
  1680.       default:
  1681.  return STATUS_FAILURE;
  1682.    }
  1683.    return STATUS_SUCCESS;
  1684. }
  1685. static unicap_status_t v4l2_queue_buffer( void *cpi_data, unicap_data_buffer_t *buffer )
  1686. {
  1687.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1688.    struct _unicap_queue *queue = malloc( sizeof( struct _unicap_queue ) );
  1689.    struct v4l2_buffer v4l2_buffer;
  1690.    TRACE( "QUEUEn" );
  1691.    if( handle->capture_running )
  1692.    {
  1693.       unicap_status_t status = queue_buffer( handle, buffer );
  1694.       if( SUCCESS( status ) )
  1695.       {
  1696.  queue->data = buffer;
  1697.  _insert_back_queue( handle->in_queue, queue );
  1698.       }
  1699.       else
  1700.       {
  1701.  TRACE( "queue buffer failedn" );
  1702.       }
  1703.       if( ( status == STATUS_NO_BUFFERS ) && ( buffer->type == UNICAP_BUFFER_TYPE_SYSTEM ) )
  1704.       {
  1705.  status = STATUS_SUCCESS;
  1706.       }
  1707.    }
  1708.    
  1709.    return STATUS_SUCCESS;
  1710. }
  1711. static unicap_status_t v4l2_dequeue_buffer( void *cpi_data, unicap_data_buffer_t **buffer )
  1712. {
  1713. /*  v4l2_handle_t handle = (v4l2_handle_t) cpi_data; */
  1714.    return STATUS_NOT_IMPLEMENTED;
  1715. }
  1716. static unicap_status_t v4l2_wait_buffer( void *cpi_data, unicap_data_buffer_t **buffer )
  1717. {
  1718.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1719.    struct v4l2_buffer v4l2_buffer;
  1720.    unicap_data_buffer_t *returned_buffer;
  1721.    struct _unicap_queue *entry;
  1722.    TRACE( "WAITn" );
  1723.    if( !handle->out_queue->next &&! handle->capture_running )
  1724.    {
  1725.       TRACE( "Wait->capture stopped" );
  1726.       return STATUS_IS_STOPPED;
  1727.    }
  1728.    
  1729.    while( !handle->out_queue->next )
  1730.    {
  1731.       usleep( 1000 );
  1732.    }
  1733.    
  1734.    if( handle->out_queue->next )
  1735.    {
  1736.       entry = _get_front_queue( handle->out_queue );
  1737.       returned_buffer = ( unicap_data_buffer_t * ) entry->data;
  1738.       free( entry );
  1739.       *buffer = returned_buffer;
  1740.    }
  1741.    
  1742.    TRACE( "-WAITn" );
  1743.    return STATUS_SUCCESS;
  1744. }
  1745. static unicap_status_t v4l2_poll_buffer( void *cpi_data, int *count )
  1746. {
  1747.    v4l2_handle_t handle = (v4l2_handle_t) cpi_data;
  1748. /*    TRACE( "POLLn" ); */
  1749.    *count = _queue_get_size( handle->out_queue );
  1750.    return STATUS_SUCCESS;
  1751. }
  1752. static unicap_status_t v4l2_set_event_notify( void *cpi_data, unicap_event_callback_t func, unicap_handle_t unicap_handle )
  1753. {
  1754.    v4l2_handle_t handle = ( v4l2_handle_t )cpi_data;
  1755.    
  1756.    handle->event_callback = func;
  1757.    handle->unicap_handle = unicap_handle;
  1758.    
  1759.    return STATUS_SUCCESS;
  1760. }
  1761.    
  1762. static void v4l2_capture_thread( v4l2_handle_t handle )
  1763. {
  1764.    unicap_data_buffer_t new_frame_buffer;
  1765.    
  1766.    handle->dqindex = -1;
  1767.    unicap_copy_format( &new_frame_buffer.format, &handle->current_format );
  1768.    new_frame_buffer.buffer_size = handle->current_format.buffer_size;
  1769.    new_frame_buffer.type = UNICAP_BUFFER_TYPE_SYSTEM;
  1770.    while( !handle->quit_capture_thread )
  1771.    {
  1772.       struct v4l2_buffer v4l2_buffer;
  1773.       struct _unicap_queue *entry;
  1774.       struct timespec abs_timeout;
  1775.       struct timeval  ctime;
  1776.       int old_index;
  1777.       
  1778.       gettimeofday( &ctime, NULL );
  1779.       abs_timeout.tv_sec = ctime.tv_sec + 1;
  1780.       abs_timeout.tv_nsec = ctime.tv_usec * 1000;      
  1781.       old_index = handle->dqindex;
  1782.       if( sem_timedwait( &handle->sema, &abs_timeout ) )
  1783.       {
  1784.  TRACE( "SEM_WAIT FAILEDn" );
  1785.  continue;
  1786.       }
  1787.       if( ( ( handle->dqindex + 1 ) % handle->buffer_count ) == handle->qindex )
  1788.       {
  1789.  sem_post( &handle->sema );
  1790.  usleep( 1000 );
  1791.  continue;
  1792.       }      
  1793.  
  1794.       v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1795.       if( handle->io_method == CPI_V4L2_IO_METHOD_MMAP )
  1796.       {
  1797.  handle->dqindex = ( handle->dqindex + 1 ) % handle->buffer_count;
  1798. /*   TRACE( "DQIndex: %dn", handle->dqindex ); */
  1799.  v4l2_buffer.index = handle->dqindex;
  1800.  
  1801.  v4l2_buffer.memory = V4L2_MEMORY_MMAP;
  1802.       }
  1803.       
  1804.       if( ioctl( handle->fd, VIDIOC_DQBUF, &v4l2_buffer ) < 0 )
  1805.       {
  1806.  TRACE( "VIDIOC_DQBUF ioctl failed: %sn", strerror( errno ) );
  1807.  handle->dqindex = old_index;
  1808.  sem_post( &handle->sema );
  1809.  usleep( 30000 );
  1810.  continue;
  1811.       }
  1812.       
  1813.       if( sem_post( &handle->sema ) )
  1814.       {
  1815.  TRACE( "SEM_POST FAILEDn" );
  1816.       }
  1817.       if( handle->event_callback )
  1818.       {
  1819.  memcpy( &new_frame_buffer.fill_time, &v4l2_buffer.timestamp, sizeof( struct timeval ) );
  1820.  new_frame_buffer.data = handle->buffers[v4l2_buffer.index].start;
  1821.  handle->event_callback( handle->unicap_handle, UNICAP_EVENT_NEW_FRAME, &new_frame_buffer );
  1822.       }
  1823.       entry = _get_front_queue( handle->in_queue );
  1824.       if( entry )
  1825.       {
  1826.  unicap_data_buffer_t *data_buffer = ( unicap_data_buffer_t * ) entry->data;
  1827.  struct _unicap_queue *outentry = malloc( sizeof( struct _unicap_queue ) );
  1828.  free( entry );
  1829.  
  1830.  switch( handle->io_method )
  1831.  {
  1832.     case CPI_V4L2_IO_METHOD_MMAP:
  1833.     {
  1834.        if( data_buffer->type == UNICAP_BUFFER_TYPE_SYSTEM )
  1835.        {
  1836.   data_buffer->buffer_size = handle->buffers[v4l2_buffer.index].length;
  1837.   data_buffer->data = handle->buffers[v4l2_buffer.index].start;
  1838.        }
  1839.        else
  1840.        {
  1841.   int length = data_buffer->buffer_size;
  1842.   if( length > handle->buffers[v4l2_buffer.index].length )
  1843.      length = handle->buffers[v4l2_buffer.index].length;
  1844.   
  1845.   memcpy( data_buffer->data, 
  1846.   handle->buffers[v4l2_buffer.index].start, 
  1847.   length);
  1848.        }
  1849.     }
  1850.     break;
  1851.     case CPI_V4L2_IO_METHOD_USERPOINTER:
  1852.     {
  1853.        data_buffer->data = ( void* )v4l2_buffer.m.userptr;
  1854.        
  1855. /*         if( returned_buffer->data != ( void* )v4l2_buffer.m.userptr ) */
  1856. /*         { */
  1857. /*    TRACE( "returned_buffer->data != v4l2_buffer.m.userptrn" ); */
  1858. /*         } */
  1859.     }
  1860.     break;
  1861.     
  1862.     default:
  1863.     {
  1864.        TRACE( "Invalid io_method!!!'n" );
  1865.        return;
  1866.     }
  1867.  }
  1868.  memcpy( &data_buffer->fill_time, &v4l2_buffer.timestamp, sizeof( struct timeval ) );
  1869.  unicap_copy_format( &data_buffer->format, &handle->current_format );
  1870.  outentry->data = data_buffer;
  1871.  _insert_back_queue( handle->out_queue, outentry );
  1872.       }      
  1873.       else
  1874.       {
  1875.  struct v4l2_buffer v4l2_buffer;
  1876.  
  1877.  if( handle->io_method == CPI_V4L2_IO_METHOD_MMAP )
  1878.  {
  1879.     while( sem_timedwait( &handle->sema, &abs_timeout ) )
  1880.     {
  1881.        TRACE( "SEM_WAIT FAILED!n" );
  1882.        gettimeofday( &ctime, NULL );
  1883.        abs_timeout.tv_sec = ctime.tv_sec + 1;
  1884.        abs_timeout.tv_nsec = ctime.tv_usec * 1000;      
  1885.        if( handle->quit_capture_thread )
  1886.        {
  1887.   return;
  1888.        }
  1889.     }
  1890.     
  1891.     v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1892.     v4l2_buffer.length = handle->current_format.buffer_size;
  1893.     v4l2_buffer.memory = V4L2_MEMORY_MMAP;
  1894.     v4l2_buffer.index = handle->qindex;
  1895. /*      TRACE( "Q: index = %d type = %u, memory = %un", handle->qindex, v4l2_buffer.type, v4l2_buffer.memory ); */
  1896.     handle->qindex = ( handle->qindex + 1 ) % handle->buffer_count;
  1897.     
  1898.  
  1899.     if( ioctl( handle->fd, VIDIOC_QBUF, &v4l2_buffer ) < 0 )
  1900.     {
  1901.        TRACE( "VIDIOC_QBUF ioctl failed: %sn", strerror( errno ) );
  1902.     }
  1903.     if( sem_post( &handle->sema ) )
  1904.     {
  1905.        TRACE( "SEM_POST FAILED!n" );
  1906.     }
  1907.  }
  1908.       }
  1909.    }   
  1910. }