2010-01-21 05:39:52 -03:00
/*
* uvc_entity . c - - USB Video Class driver
*
* Copyright ( C ) 2005 - 2011
* Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
*/
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/videodev2.h>
# include <media/v4l2-common.h>
# include "uvcvideo.h"
/* ------------------------------------------------------------------------
* Video subdevices registration and unregistration
*/
static int uvc_mc_register_entity ( struct uvc_video_chain * chain ,
struct uvc_entity * entity )
{
const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE ;
2011-06-28 18:17:48 -03:00
struct media_entity * sink ;
2010-01-21 05:39:52 -03:00
unsigned int i ;
2011-06-28 18:17:48 -03:00
int ret ;
sink = ( UVC_ENTITY_TYPE ( entity ) = = UVC_TT_STREAMING )
? ( entity - > vdev ? & entity - > vdev - > entity : NULL )
: & entity - > subdev . entity ;
if ( sink = = NULL )
return 0 ;
2010-01-21 05:39:52 -03:00
for ( i = 0 ; i < entity - > num_pads ; + + i ) {
2010-01-21 08:56:19 -03:00
struct media_entity * source ;
2011-06-28 18:17:48 -03:00
struct uvc_entity * remote ;
u8 remote_pad ;
2010-01-21 08:56:19 -03:00
2010-01-21 05:39:52 -03:00
if ( ! ( entity - > pads [ i ] . flags & MEDIA_PAD_FL_SINK ) )
continue ;
remote = uvc_entity_by_id ( chain - > dev , entity - > baSourceID [ i ] ) ;
if ( remote = = NULL )
return - EINVAL ;
2011-09-06 19:16:18 -03:00
source = ( UVC_ENTITY_TYPE ( remote ) = = UVC_TT_STREAMING )
2011-06-28 18:17:48 -03:00
? ( remote - > vdev ? & remote - > vdev - > entity : NULL )
: & remote - > subdev . entity ;
if ( source = = NULL )
continue ;
2010-01-21 08:56:19 -03:00
2010-01-21 05:39:52 -03:00
remote_pad = remote - > num_pads - 1 ;
2010-01-21 08:56:19 -03:00
ret = media_entity_create_link ( source , remote_pad ,
sink , i , flags ) ;
2010-01-21 05:39:52 -03:00
if ( ret < 0 )
return ret ;
}
2011-06-28 18:17:48 -03:00
if ( UVC_ENTITY_TYPE ( entity ) = = UVC_TT_STREAMING )
return 0 ;
2010-01-21 08:56:19 -03:00
2011-06-28 18:17:48 -03:00
return v4l2_device_register_subdev ( & chain - > dev - > vdev , & entity - > subdev ) ;
2010-01-21 05:39:52 -03:00
}
static struct v4l2_subdev_ops uvc_subdev_ops = {
} ;
void uvc_mc_cleanup_entity ( struct uvc_entity * entity )
{
2010-01-21 08:56:19 -03:00
if ( UVC_ENTITY_TYPE ( entity ) ! = UVC_TT_STREAMING )
media_entity_cleanup ( & entity - > subdev . entity ) ;
else if ( entity - > vdev ! = NULL )
media_entity_cleanup ( & entity - > vdev - > entity ) ;
2010-01-21 05:39:52 -03:00
}
static int uvc_mc_init_entity ( struct uvc_entity * entity )
{
2010-01-21 08:56:19 -03:00
int ret ;
if ( UVC_ENTITY_TYPE ( entity ) ! = UVC_TT_STREAMING ) {
v4l2_subdev_init ( & entity - > subdev , & uvc_subdev_ops ) ;
strlcpy ( entity - > subdev . name , entity - > name ,
sizeof ( entity - > subdev . name ) ) ;
ret = media_entity_init ( & entity - > subdev . entity ,
entity - > num_pads , entity - > pads , 0 ) ;
2011-06-28 18:17:48 -03:00
} else if ( entity - > vdev ! = NULL ) {
2010-01-21 08:56:19 -03:00
ret = media_entity_init ( & entity - > vdev - > entity ,
entity - > num_pads , entity - > pads , 0 ) ;
2011-06-28 18:17:48 -03:00
} else
ret = 0 ;
2010-01-21 05:39:52 -03:00
2010-01-21 08:56:19 -03:00
return ret ;
2010-01-21 05:39:52 -03:00
}
int uvc_mc_register_entities ( struct uvc_video_chain * chain )
{
struct uvc_entity * entity ;
int ret ;
list_for_each_entry ( entity , & chain - > entities , chain ) {
ret = uvc_mc_init_entity ( entity ) ;
if ( ret < 0 ) {
uvc_printk ( KERN_INFO , " Failed to initialize entity for "
" entity %u \n " , entity - > id ) ;
return ret ;
}
}
list_for_each_entry ( entity , & chain - > entities , chain ) {
ret = uvc_mc_register_entity ( chain , entity ) ;
if ( ret < 0 ) {
uvc_printk ( KERN_INFO , " Failed to register entity for "
" entity %u \n " , entity - > id ) ;
return ret ;
}
}
return 0 ;
}