2017-12-01 16:47:10 +03:00
// SPDX-License-Identifier: GPL-2.0
// tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
MAINTAINERS & files: Canonize the e-mails I use at files
From now on, I'll start using my @kernel.org as my development e-mail.
As such, let's remove the entries that point to the old
mchehab@s-opensource.com at MAINTAINERS file.
For the files written with a copyright with mchehab@s-opensource,
let's keep Samsung on their names, using mchehab+samsung@kernel.org,
in order to keep pointing to my employer, with sponsors the work.
For the files written before I join Samsung (on July, 4 2013),
let's just use mchehab@kernel.org.
For bug reports, we can simply point to just kernel.org, as
this will reach my mchehab+samsung inbox anyway.
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Brian Warner <brian.warner@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
2018-04-25 12:34:48 +03:00
// Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
2017-12-01 16:47:10 +03:00
//
// Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
// - Fixed module load/unload
2011-08-04 11:14:01 +04:00
2009-09-14 16:42:41 +04:00
# include <linux/module.h>
# include <linux/delay.h>
# include <linux/errno.h>
# include <linux/fs.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/mm.h>
# include <linux/ioport.h>
# include <linux/init.h>
# include <linux/sched.h>
# include <linux/random.h>
# include <linux/usb.h>
# include <linux/videodev2.h>
2008-10-25 17:43:04 +04:00
# include <media/v4l2-ioctl.h>
2012-09-11 18:50:37 +04:00
# include <media/v4l2-event.h>
2011-05-09 23:53:50 +04:00
# include <media/tuner.h>
2009-09-14 16:42:41 +04:00
# include <linux/interrupt.h>
# include <linux/kthread.h>
# include <linux/highmem.h>
# include <linux/freezer.h>
# include "tm6000-regs.h"
# include "tm6000.h"
# define BUFFER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
2007-07-24 15:06:45 +04:00
/* Limits minimum and default number of buffers */
# define TM6000_MIN_BUF 4
# define TM6000_DEF_BUF 8
2012-10-04 17:04:28 +04:00
# define TM6000_NUM_URB_BUF 8
2010-05-19 20:58:27 +04:00
# define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */
2008-01-10 23:27:26 +03:00
2009-09-14 16:42:41 +04:00
/* Declare static vars that will be used as parameters */
static unsigned int vid_limit = 16 ; /* Video memory limit, in Mb */
static int video_nr = - 1 ; /* /dev/videoN, -1 for autodetect */
2011-02-18 04:11:05 +03:00
static int radio_nr = - 1 ; /* /dev/radioN, -1 for autodetect */
2012-12-20 21:21:23 +04:00
static bool keep_urb ; /* keep urb buffers allocated */
2009-09-14 16:42:41 +04:00
/* Debug level */
int tm6000_debug ;
2010-06-05 04:08:25 +04:00
EXPORT_SYMBOL_GPL ( tm6000_debug ) ;
2009-09-14 16:42:41 +04:00
static struct tm6000_fmt format [ ] = {
{
. name = " 4:2:2, packed, YVY2 " ,
. fourcc = V4L2_PIX_FMT_YUYV ,
. depth = 16 ,
2008-01-10 04:44:51 +03:00
} , {
2009-09-14 16:42:41 +04:00
. name = " 4:2:2, packed, UYVY " ,
. fourcc = V4L2_PIX_FMT_UYVY ,
. depth = 16 ,
2008-01-10 04:44:51 +03:00
} , {
2009-09-14 16:42:41 +04:00
. name = " A/V + VBI mux packet " ,
. fourcc = V4L2_PIX_FMT_TM6000 ,
. depth = 16 ,
}
} ;
/* ------------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* DMA and thread functions
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-14 16:42:41 +04:00
# define norm_maxw(a) 720
2007-09-04 04:51:45 +04:00
# define norm_maxh(a) 576
2009-09-14 16:42:41 +04:00
# define norm_minw(a) norm_maxw(a)
# define norm_minh(a) norm_maxh(a)
/*
* video - buf generic routine to get the next available buffer
*/
2008-10-26 15:18:53 +03:00
static inline void get_next_buf ( struct tm6000_dmaqueue * dma_q ,
2008-01-10 04:44:51 +03:00
struct tm6000_buffer * * buf )
2009-09-14 16:42:41 +04:00
{
2008-01-10 04:44:51 +03:00
struct tm6000_core * dev = container_of ( dma_q , struct tm6000_core , vidq ) ;
2009-09-14 16:42:41 +04:00
if ( list_empty ( & dma_q - > active ) ) {
2008-01-10 04:44:51 +03:00
dprintk ( dev , V4L2_DEBUG_QUEUE , " No active queue to serve \n " ) ;
2008-11-28 12:44:06 +03:00
* buf = NULL ;
2008-10-26 15:18:53 +03:00
return ;
2009-09-14 16:42:41 +04:00
}
* buf = list_entry ( dma_q - > active . next ,
struct tm6000_buffer , vb . queue ) ;
}
/*
* Announces that a buffer were filled and request the next
*/
2008-01-10 04:44:51 +03:00
static inline void buffer_filled ( struct tm6000_core * dev ,
struct tm6000_dmaqueue * dma_q ,
struct tm6000_buffer * buf )
2009-09-14 16:42:41 +04:00
{
/* Advice that buffer was filled */
2008-01-10 04:44:51 +03:00
dprintk ( dev , V4L2_DEBUG_ISOC , " [%p/%d] wakeup \n " , buf , buf - > vb . i ) ;
2007-11-15 22:37:35 +03:00
buf - > vb . state = VIDEOBUF_DONE ;
2009-09-14 16:42:41 +04:00
buf - > vb . field_count + + ;
2019-01-21 16:32:23 +03:00
buf - > vb . ts = ktime_get_ns ( ) ;
2009-09-14 16:42:41 +04:00
list_del ( & buf - > vb . queue ) ;
wake_up ( & buf - > vb . done ) ;
}
/*
* Identify the tm5600 / 6000 buffer header type and properly handles
*/
2010-05-19 20:58:26 +04:00
static int copy_streams ( u8 * data , unsigned long len ,
struct urb * urb )
2007-09-19 22:39:22 +04:00
{
struct tm6000_dmaqueue * dma_q = urb - > context ;
2010-10-20 13:35:12 +04:00
struct tm6000_core * dev = container_of ( dma_q , struct tm6000_core , vidq ) ;
2012-04-20 14:30:48 +04:00
u8 * ptr = data , * endp = data + len ;
2010-10-20 13:35:12 +04:00
unsigned long header = 0 ;
int rc = 0 ;
2010-06-01 19:47:42 +04:00
unsigned int cmd , cpysize , pktsize , size , field , block , line , pos = 0 ;
2011-04-12 01:49:24 +04:00
struct tm6000_buffer * vbuf = NULL ;
2010-06-01 19:47:42 +04:00
char * voutp = NULL ;
unsigned int linewidth ;
2011-02-18 04:11:05 +03:00
if ( ! dev - > radio ) {
/* get video buffer */
get_next_buf ( dma_q , & vbuf ) ;
if ( ! vbuf )
return rc ;
voutp = videobuf_to_vmalloc ( & vbuf - > vb ) ;
if ( ! voutp )
return 0 ;
}
2008-04-09 15:07:20 +04:00
2010-06-01 19:47:42 +04:00
for ( ptr = data ; ptr < endp ; ) {
2008-04-09 15:07:20 +04:00
if ( ! dev - > isoc_ctl . cmd ) {
2010-06-01 19:47:42 +04:00
/* Header */
if ( dev - > isoc_ctl . tmp_buf_len > 0 ) {
/* from last urb or packet */
header = dev - > isoc_ctl . tmp_buf ;
if ( 4 - dev - > isoc_ctl . tmp_buf_len > 0 ) {
2010-10-20 13:35:12 +04:00
memcpy ( ( u8 * ) & header +
2010-05-03 00:14:33 +04:00
dev - > isoc_ctl . tmp_buf_len ,
2008-04-09 15:07:20 +04:00
ptr ,
2010-05-03 00:14:33 +04:00
4 - dev - > isoc_ctl . tmp_buf_len ) ;
ptr + = 4 - dev - > isoc_ctl . tmp_buf_len ;
2008-04-09 15:07:20 +04:00
}
2010-06-01 19:47:42 +04:00
dev - > isoc_ctl . tmp_buf_len = 0 ;
} else {
if ( ptr + 3 > = endp ) {
/* have incomplete header */
dev - > isoc_ctl . tmp_buf_len = endp - ptr ;
2010-10-20 13:35:12 +04:00
memcpy ( & dev - > isoc_ctl . tmp_buf , ptr ,
2010-06-01 19:47:42 +04:00
dev - > isoc_ctl . tmp_buf_len ) ;
return rc ;
}
/* Seek for sync */
for ( ; ptr < endp - 3 ; ptr + + ) {
if ( * ( ptr + 3 ) = = 0x47 )
break ;
}
/* Get message header */
header = * ( unsigned long * ) ptr ;
ptr + = 4 ;
2008-04-09 15:07:20 +04:00
}
2010-06-07 18:57:28 +04:00
2010-06-01 19:47:42 +04:00
/* split the header fields */
size = ( ( header & 0x7e ) < < 1 ) ;
if ( size > 0 )
size - = 4 ;
block = ( header > > 7 ) & 0xf ;
field = ( header > > 11 ) & 0x1 ;
line = ( header > > 12 ) & 0x1ff ;
cmd = ( header > > 21 ) & 0x7 ;
2019-02-18 22:29:03 +03:00
/* Validates header fields */
2010-06-01 19:47:42 +04:00
if ( size > TM6000_URB_MSG_LEN )
size = TM6000_URB_MSG_LEN ;
pktsize = TM6000_URB_MSG_LEN ;
2011-08-04 11:14:01 +04:00
/*
* calculate position in buffer and change the buffer
2010-06-01 19:47:42 +04:00
*/
switch ( cmd ) {
case TM6000_URB_MSG_VIDEO :
2011-02-18 04:11:05 +03:00
if ( ! dev - > radio ) {
if ( ( dev - > isoc_ctl . vfield ! = field ) & &
( field = = 1 ) ) {
2011-08-04 11:14:01 +04:00
/*
* Announces that a new buffer
* were filled
*/
2011-02-18 04:11:05 +03:00
buffer_filled ( dev , dma_q , vbuf ) ;
dprintk ( dev , V4L2_DEBUG_ISOC ,
2010-06-01 19:47:42 +04:00
" new buffer filled \n " ) ;
2011-02-18 04:11:05 +03:00
get_next_buf ( dma_q , & vbuf ) ;
if ( ! vbuf )
return rc ;
voutp = videobuf_to_vmalloc ( & vbuf - > vb ) ;
if ( ! voutp )
return rc ;
memset ( voutp , 0 , vbuf - > vb . size ) ;
}
linewidth = vbuf - > vb . width < < 1 ;
pos = ( ( line < < 1 ) - field - 1 ) *
linewidth + block * TM6000_URB_MSG_LEN ;
/* Don't allow to write out of the buffer */
if ( pos + size > vbuf - > vb . size )
cmd = TM6000_URB_MSG_ERR ;
dev - > isoc_ctl . vfield = field ;
2011-04-12 01:49:24 +04:00
}
2010-06-01 19:47:42 +04:00
break ;
case TM6000_URB_MSG_VBI :
2010-06-07 18:57:28 +04:00
break ;
case TM6000_URB_MSG_AUDIO :
2010-06-01 19:47:42 +04:00
case TM6000_URB_MSG_PTS :
2011-08-04 11:14:01 +04:00
size = pktsize ; /* Size is always 180 bytes */
2010-06-01 19:47:42 +04:00
break ;
2009-09-14 16:42:41 +04:00
}
2010-06-01 19:47:42 +04:00
} else {
/* Continue the last copy */
cmd = dev - > isoc_ctl . cmd ;
size = dev - > isoc_ctl . size ;
pos = dev - > isoc_ctl . pos ;
pktsize = dev - > isoc_ctl . pktsize ;
2011-05-21 10:05:38 +04:00
field = dev - > isoc_ctl . field ;
2010-06-01 19:47:42 +04:00
}
cpysize = ( endp - ptr > size ) ? size : endp - ptr ;
if ( cpysize ) {
/* copy data in different buffers */
switch ( cmd ) {
case TM6000_URB_MSG_VIDEO :
/* Fills video buffer */
if ( vbuf )
2010-10-20 13:35:12 +04:00
memcpy ( & voutp [ pos ] , ptr , cpysize ) ;
2010-06-01 19:47:42 +04:00
break ;
2011-05-09 23:54:00 +04:00
case TM6000_URB_MSG_AUDIO : {
int i ;
for ( i = 0 ; i < cpysize ; i + = 2 )
swab16s ( ( u16 * ) ( ptr + i ) ) ;
2010-09-21 00:07:15 +04:00
2010-06-04 00:16:28 +04:00
tm6000_call_fillbuf ( dev , TM6000_AUDIO , ptr , cpysize ) ;
2010-06-01 19:47:42 +04:00
break ;
2011-05-09 23:54:00 +04:00
}
2010-06-01 19:47:42 +04:00
case TM6000_URB_MSG_VBI :
/* Need some code to copy vbi buffer */
break ;
2011-05-09 23:54:02 +04:00
case TM6000_URB_MSG_PTS : {
2010-06-01 19:47:42 +04:00
/* Need some code to copy pts */
2011-05-09 23:54:02 +04:00
u32 pts ;
pts = * ( u32 * ) ptr ;
2011-05-21 10:05:38 +04:00
dprintk ( dev , V4L2_DEBUG_ISOC , " field %d, PTS %x " ,
field , pts ) ;
2010-06-01 19:47:42 +04:00
break ;
2007-09-19 23:24:05 +04:00
}
2011-05-09 23:54:02 +04:00
}
2008-04-09 15:07:20 +04:00
}
2010-07-01 00:24:28 +04:00
if ( ptr + pktsize > endp ) {
2011-08-04 11:14:01 +04:00
/*
* End of URB packet , but cmd processing is not
2010-06-01 19:47:42 +04:00
* complete . Preserve the state for a next packet
*/
dev - > isoc_ctl . pos = pos + cpysize ;
dev - > isoc_ctl . size = size - cpysize ;
dev - > isoc_ctl . cmd = cmd ;
2011-05-21 10:05:38 +04:00
dev - > isoc_ctl . field = field ;
2010-06-01 19:47:42 +04:00
dev - > isoc_ctl . pktsize = pktsize - ( endp - ptr ) ;
2010-07-01 00:24:28 +04:00
ptr + = endp - ptr ;
2010-06-01 19:47:42 +04:00
} else {
dev - > isoc_ctl . cmd = 0 ;
ptr + = pktsize ;
2007-09-22 09:06:25 +04:00
}
2009-09-14 16:42:41 +04:00
}
2007-09-22 09:06:25 +04:00
return 0 ;
2009-09-14 16:42:41 +04:00
}
2010-06-01 19:47:42 +04:00
2009-09-14 16:42:41 +04:00
/*
* Identify the tm5600 / 6000 buffer header type and properly handles
*/
2010-05-19 20:58:26 +04:00
static int copy_multiplexed ( u8 * ptr , unsigned long len ,
struct urb * urb )
2009-09-14 16:42:41 +04:00
{
struct tm6000_dmaqueue * dma_q = urb - > context ;
2010-10-20 13:35:12 +04:00
struct tm6000_core * dev = container_of ( dma_q , struct tm6000_core , vidq ) ;
unsigned int pos = dev - > isoc_ctl . pos , cpysize ;
int rc = 1 ;
2010-05-19 20:58:26 +04:00
struct tm6000_buffer * buf ;
char * outp = NULL ;
get_next_buf ( dma_q , & buf ) ;
if ( buf )
outp = videobuf_to_vmalloc ( & buf - > vb ) ;
if ( ! outp )
return 0 ;
2008-04-09 15:07:20 +04:00
2010-10-20 13:35:12 +04:00
while ( len > 0 ) {
cpysize = min ( len , buf - > vb . size - pos ) ;
2010-05-19 20:58:26 +04:00
memcpy ( & outp [ pos ] , ptr , cpysize ) ;
2010-10-20 13:35:12 +04:00
pos + = cpysize ;
ptr + = cpysize ;
len - = cpysize ;
2010-05-19 20:58:26 +04:00
if ( pos > = buf - > vb . size ) {
2010-10-20 13:35:12 +04:00
pos = 0 ;
2009-09-14 16:42:41 +04:00
/* Announces that a new buffer were filled */
2010-10-20 13:35:12 +04:00
buffer_filled ( dev , dma_q , buf ) ;
2007-08-27 14:55:05 +04:00
dprintk ( dev , V4L2_DEBUG_ISOC , " new buffer filled \n " ) ;
2010-10-20 13:35:12 +04:00
get_next_buf ( dma_q , & buf ) ;
2010-05-19 20:58:26 +04:00
if ( ! buf )
2009-09-14 16:42:41 +04:00
break ;
2010-05-19 20:58:26 +04:00
outp = videobuf_to_vmalloc ( & ( buf - > vb ) ) ;
if ( ! outp )
2008-11-28 13:39:00 +03:00
return rc ;
pos = 0 ;
2009-09-14 16:42:41 +04:00
}
}
2010-10-20 13:35:12 +04:00
dev - > isoc_ctl . pos = pos ;
2009-09-14 16:42:41 +04:00
return rc ;
}
2010-10-20 13:35:12 +04:00
static inline void print_err_status ( struct tm6000_core * dev ,
2008-04-09 15:07:20 +04:00
int packet , int status )
2007-08-27 14:55:05 +04:00
{
char * errmsg = " Unknown " ;
2010-10-20 13:35:12 +04:00
switch ( status ) {
2007-08-27 14:55:05 +04:00
case - ENOENT :
2017-11-02 13:11:53 +03:00
errmsg = " unlinked synchronously " ;
2007-08-27 14:55:05 +04:00
break ;
case - ECONNRESET :
2017-11-02 13:11:53 +03:00
errmsg = " unlinked asynchronously " ;
2007-08-27 14:55:05 +04:00
break ;
case - ENOSR :
errmsg = " Buffer error (overrun) " ;
break ;
case - EPIPE :
errmsg = " Stalled (device not responding) " ;
break ;
case - EOVERFLOW :
errmsg = " Babble (bad cable?) " ;
break ;
case - EPROTO :
errmsg = " Bit-stuff error (bad cable?) " ;
break ;
case - EILSEQ :
errmsg = " CRC/Timeout (could be anything) " ;
break ;
case - ETIME :
errmsg = " Device does not respond " ;
break ;
}
2010-10-20 13:35:12 +04:00
if ( packet < 0 ) {
2007-08-27 14:55:05 +04:00
dprintk ( dev , V4L2_DEBUG_QUEUE , " URB status %d [%s]. \n " ,
status , errmsg ) ;
} else {
2008-04-09 15:07:20 +04:00
dprintk ( dev , V4L2_DEBUG_QUEUE , " URB packet %d, status %d [%s]. \n " ,
2007-08-27 14:55:05 +04:00
packet , status , errmsg ) ;
}
}
2009-09-14 16:42:41 +04:00
/*
* Controls the isoc copy of each urb packet
*/
2008-11-28 13:39:00 +03:00
static inline int tm6000_isoc_copy ( struct urb * urb )
2009-09-14 16:42:41 +04:00
{
struct tm6000_dmaqueue * dma_q = urb - > context ;
2010-10-20 13:35:12 +04:00
struct tm6000_core * dev = container_of ( dma_q , struct tm6000_core , vidq ) ;
int i , len = 0 , rc = 1 , status ;
2010-05-19 20:58:26 +04:00
char * p ;
2009-09-14 16:42:41 +04:00
2010-05-19 20:58:26 +04:00
if ( urb - > status < 0 ) {
2010-10-20 13:35:12 +04:00
print_err_status ( dev , - 1 , urb - > status ) ;
2007-08-27 14:55:05 +04:00
return 0 ;
}
2009-09-14 16:42:41 +04:00
for ( i = 0 ; i < urb - > number_of_packets ; i + + ) {
2010-05-19 20:58:26 +04:00
status = urb - > iso_frame_desc [ i ] . status ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
if ( status < 0 ) {
print_err_status ( dev , i , status ) ;
2009-09-14 16:42:41 +04:00
continue ;
2007-08-27 14:55:05 +04:00
}
2009-09-14 16:42:41 +04:00
2010-05-19 20:58:26 +04:00
len = urb - > iso_frame_desc [ i ] . actual_length ;
2008-04-09 15:07:20 +04:00
2010-05-19 20:58:26 +04:00
if ( len > 0 ) {
p = urb - > transfer_buffer + urb - > iso_frame_desc [ i ] . offset ;
2008-04-09 15:07:20 +04:00
if ( ! urb - > iso_frame_desc [ i ] . status ) {
2010-10-20 13:35:12 +04:00
if ( ( dev - > fourcc ) = = V4L2_PIX_FMT_TM6000 ) {
rc = copy_multiplexed ( p , len , urb ) ;
if ( rc < = 0 )
2008-04-09 15:07:20 +04:00
return rc ;
} else {
2010-05-19 20:58:26 +04:00
copy_streams ( p , len , urb ) ;
2008-04-09 15:07:20 +04:00
}
}
2010-05-19 20:58:26 +04:00
}
2009-09-14 16:42:41 +04:00
}
return rc ;
}
/* ------------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* URB control
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-14 16:42:41 +04:00
/*
* IRQ callback , called by URB callback
*/
static void tm6000_irq_callback ( struct urb * urb )
{
struct tm6000_dmaqueue * dma_q = urb - > context ;
2008-01-10 04:44:51 +03:00
struct tm6000_core * dev = container_of ( dma_q , struct tm6000_core , vidq ) ;
2018-09-10 12:19:59 +03:00
unsigned long flags ;
2008-11-28 13:39:00 +03:00
int i ;
2009-09-14 16:42:41 +04:00
2011-08-04 11:14:06 +04:00
switch ( urb - > status ) {
case 0 :
case - ETIMEDOUT :
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
2008-10-26 15:18:53 +03:00
return ;
2007-09-22 09:06:25 +04:00
2011-08-04 11:14:06 +04:00
default :
tm6000_err ( " urb completion error %d. \n " , urb - > status ) ;
break ;
}
2018-09-10 12:19:59 +03:00
spin_lock_irqsave ( & dev - > slock , flags ) ;
2008-11-28 13:39:00 +03:00
tm6000_isoc_copy ( urb ) ;
2018-09-10 12:19:59 +03:00
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2009-09-14 16:42:41 +04:00
2008-11-28 13:39:00 +03:00
/* Reset urb buffers */
for ( i = 0 ; i < urb - > number_of_packets ; i + + ) {
urb - > iso_frame_desc [ i ] . status = 0 ;
urb - > iso_frame_desc [ i ] . actual_length = 0 ;
}
2009-09-14 16:42:41 +04:00
2008-01-10 04:44:51 +03:00
urb - > status = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( urb - > status )
2009-09-14 16:42:41 +04:00
tm6000_err ( " urb resubmit failed (error=%i) \n " ,
urb - > status ) ;
}
2012-10-04 17:04:28 +04:00
/*
* Allocate URB buffers
*/
static int tm6000_alloc_urb_buffers ( struct tm6000_core * dev )
{
int num_bufs = TM6000_NUM_URB_BUF ;
int i ;
2017-09-14 15:34:39 +03:00
if ( dev - > urb_buffer )
2012-10-04 17:04:28 +04:00
return 0 ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 23:55:00 +03:00
dev - > urb_buffer = kmalloc_array ( num_bufs , sizeof ( void * ) , GFP_KERNEL ) ;
2017-09-14 15:34:39 +03:00
if ( ! dev - > urb_buffer )
2012-10-04 17:04:28 +04:00
return - ENOMEM ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 23:55:00 +03:00
dev - > urb_dma = kmalloc_array ( num_bufs , sizeof ( dma_addr_t * ) ,
GFP_KERNEL ) ;
2017-09-14 15:34:39 +03:00
if ( ! dev - > urb_dma )
2012-10-04 17:04:28 +04:00
return - ENOMEM ;
for ( i = 0 ; i < num_bufs ; i + + ) {
dev - > urb_buffer [ i ] = usb_alloc_coherent (
dev - > udev , dev - > urb_size ,
GFP_KERNEL , & dev - > urb_dma [ i ] ) ;
if ( ! dev - > urb_buffer [ i ] ) {
tm6000_err ( " unable to allocate %i bytes for transfer buffer %i \n " ,
dev - > urb_size , i ) ;
return - ENOMEM ;
}
memset ( dev - > urb_buffer [ i ] , 0 , dev - > urb_size ) ;
}
return 0 ;
}
/*
* Free URB buffers
*/
static int tm6000_free_urb_buffers ( struct tm6000_core * dev )
{
int i ;
2017-09-14 15:34:39 +03:00
if ( ! dev - > urb_buffer )
2012-10-04 17:04:28 +04:00
return 0 ;
for ( i = 0 ; i < TM6000_NUM_URB_BUF ; i + + ) {
if ( dev - > urb_buffer [ i ] ) {
usb_free_coherent ( dev - > udev ,
dev - > urb_size ,
dev - > urb_buffer [ i ] ,
dev - > urb_dma [ i ] ) ;
dev - > urb_buffer [ i ] = NULL ;
}
}
kfree ( dev - > urb_buffer ) ;
kfree ( dev - > urb_dma ) ;
dev - > urb_buffer = NULL ;
dev - > urb_dma = NULL ;
return 0 ;
}
2009-09-14 16:42:41 +04:00
/*
* Stop and Deallocate URBs
*/
static void tm6000_uninit_isoc ( struct tm6000_core * dev )
{
struct urb * urb ;
int i ;
2008-01-10 23:27:26 +03:00
dev - > isoc_ctl . buf = NULL ;
2009-09-14 16:42:41 +04:00
for ( i = 0 ; i < dev - > isoc_ctl . num_bufs ; i + + ) {
2010-10-20 13:35:12 +04:00
urb = dev - > isoc_ctl . urb [ i ] ;
2009-09-14 16:42:41 +04:00
if ( urb ) {
usb_kill_urb ( urb ) ;
usb_unlink_urb ( urb ) ;
usb_free_urb ( urb ) ;
dev - > isoc_ctl . urb [ i ] = NULL ;
}
dev - > isoc_ctl . transfer_buffer [ i ] = NULL ;
}
2012-10-04 17:04:28 +04:00
if ( ! keep_urb )
tm6000_free_urb_buffers ( dev ) ;
2010-10-20 13:35:12 +04:00
kfree ( dev - > isoc_ctl . urb ) ;
kfree ( dev - > isoc_ctl . transfer_buffer ) ;
2008-04-09 08:49:19 +04:00
2010-10-20 13:35:12 +04:00
dev - > isoc_ctl . urb = NULL ;
dev - > isoc_ctl . transfer_buffer = NULL ;
2008-04-09 08:49:19 +04:00
dev - > isoc_ctl . num_bufs = 0 ;
2009-09-14 16:42:41 +04:00
}
/*
2012-10-04 17:04:28 +04:00
* Assign URBs and start IRQ
2009-09-14 16:42:41 +04:00
*/
2011-02-18 04:11:05 +03:00
static int tm6000_prepare_isoc ( struct tm6000_core * dev )
2009-09-14 16:42:41 +04:00
{
struct tm6000_dmaqueue * dma_q = & dev - > vidq ;
2012-10-04 17:04:28 +04:00
int i , j , sb_size , pipe , size , max_packets ;
int num_bufs = TM6000_NUM_URB_BUF ;
2009-09-14 16:42:41 +04:00
struct urb * urb ;
2008-01-10 00:12:39 +03:00
2009-09-14 16:42:41 +04:00
/* De-allocates all pending stuff */
tm6000_uninit_isoc ( dev ) ;
2010-12-22 11:57:46 +03:00
/* Stop interrupt USB pipe */
tm6000_ir_int_stop ( dev ) ;
2009-09-14 16:42:41 +04:00
2010-04-26 18:24:18 +04:00
usb_set_interface ( dev - > udev ,
dev - > isoc_in . bInterfaceNumber ,
dev - > isoc_in . bAlternateSetting ) ;
2010-12-22 11:57:46 +03:00
/* Start interrupt USB pipe */
tm6000_ir_int_start ( dev ) ;
2008-01-10 23:27:26 +03:00
pipe = usb_rcvisocpipe ( dev - > udev ,
2010-04-26 18:24:18 +04:00
dev - > isoc_in . endp - > desc . bEndpointAddress &
2008-01-10 23:27:26 +03:00
USB_ENDPOINT_NUMBER_MASK ) ;
size = usb_maxpacket ( dev - > udev , pipe , usb_pipeout ( pipe ) ) ;
2010-04-26 18:24:18 +04:00
if ( size > dev - > isoc_in . maxsize )
size = dev - > isoc_in . maxsize ;
2008-01-10 23:27:26 +03:00
dev - > isoc_ctl . max_pkt_size = size ;
2011-02-18 04:11:05 +03:00
max_packets = TM6000_MAX_ISO_PACKETS ;
2008-01-10 23:27:26 +03:00
sb_size = max_packets * size ;
2012-10-04 17:04:28 +04:00
dev - > urb_size = sb_size ;
2008-01-10 23:27:26 +03:00
dev - > isoc_ctl . num_bufs = num_bufs ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 23:55:00 +03:00
dev - > isoc_ctl . urb = kmalloc_array ( num_bufs , sizeof ( void * ) ,
GFP_KERNEL ) ;
2017-09-14 15:34:39 +03:00
if ( ! dev - > isoc_ctl . urb )
2009-09-14 16:42:41 +04:00
return - ENOMEM ;
treewide: kmalloc() -> kmalloc_array()
The kmalloc() function has a 2-factor argument form, kmalloc_array(). This
patch replaces cases of:
kmalloc(a * b, gfp)
with:
kmalloc_array(a * b, gfp)
as well as handling cases of:
kmalloc(a * b * c, gfp)
with:
kmalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kmalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kmalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The tools/ directory was manually excluded, since it has its own
implementation of kmalloc().
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kmalloc
+ kmalloc_array
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kmalloc(sizeof(THING) * C2, ...)
|
kmalloc(sizeof(TYPE) * C2, ...)
|
kmalloc(C1 * C2 * C3, ...)
|
kmalloc(C1 * C2, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * E2
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kmalloc
+ kmalloc_array
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 23:55:00 +03:00
dev - > isoc_ctl . transfer_buffer = kmalloc_array ( num_bufs ,
sizeof ( void * ) ,
GFP_KERNEL ) ;
2010-02-11 09:30:30 +03:00
if ( ! dev - > isoc_ctl . transfer_buffer ) {
2009-09-14 16:42:41 +04:00
kfree ( dev - > isoc_ctl . urb ) ;
return - ENOMEM ;
}
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:19 +03:00
dprintk ( dev , V4L2_DEBUG_QUEUE , " Allocating %d x %d packets (%d bytes) of %d bytes each to handle %u size \n " ,
2008-01-10 23:27:26 +03:00
max_packets , num_bufs , sb_size ,
2010-04-26 18:24:18 +04:00
dev - > isoc_in . maxsize , size ) ;
2009-09-14 16:42:41 +04:00
2012-10-04 17:04:28 +04:00
2015-06-05 15:33:44 +03:00
if ( tm6000_alloc_urb_buffers ( dev ) < 0 ) {
2012-10-04 17:04:28 +04:00
tm6000_err ( " cannot allocate memory for urb buffers \n " ) ;
/* call free, as some buffers might have been allocated */
tm6000_free_urb_buffers ( dev ) ;
kfree ( dev - > isoc_ctl . urb ) ;
kfree ( dev - > isoc_ctl . transfer_buffer ) ;
return - ENOMEM ;
}
2009-09-14 16:42:41 +04:00
/* allocate urbs and transfer buffers */
for ( i = 0 ; i < dev - > isoc_ctl . num_bufs ; i + + ) {
urb = usb_alloc_urb ( max_packets , GFP_KERNEL ) ;
if ( ! urb ) {
tm6000_uninit_isoc ( dev ) ;
2017-02-23 01:32:19 +03:00
tm6000_free_urb_buffers ( dev ) ;
2009-09-14 16:42:41 +04:00
return - ENOMEM ;
}
dev - > isoc_ctl . urb [ i ] = urb ;
2012-10-04 17:04:28 +04:00
urb - > transfer_dma = dev - > urb_dma [ i ] ;
dev - > isoc_ctl . transfer_buffer [ i ] = dev - > urb_buffer [ i ] ;
2009-09-14 16:42:41 +04:00
2008-01-10 23:27:26 +03:00
usb_fill_bulk_urb ( urb , dev - > udev , pipe ,
dev - > isoc_ctl . transfer_buffer [ i ] , sb_size ,
tm6000_irq_callback , dma_q ) ;
2010-04-26 18:24:18 +04:00
urb - > interval = dev - > isoc_in . endp - > desc . bInterval ;
2009-09-14 16:42:41 +04:00
urb - > number_of_packets = max_packets ;
2008-01-10 23:27:26 +03:00
urb - > transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP ;
2009-09-14 16:42:41 +04:00
for ( j = 0 ; j < max_packets ; j + + ) {
2008-01-10 23:27:26 +03:00
urb - > iso_frame_desc [ j ] . offset = size * j ;
urb - > iso_frame_desc [ j ] . length = size ;
2009-09-14 16:42:41 +04:00
}
}
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int tm6000_start_thread ( struct tm6000_core * dev )
2009-09-14 16:42:41 +04:00
{
2008-04-09 08:49:19 +04:00
struct tm6000_dmaqueue * dma_q = & dev - > vidq ;
int i ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
dma_q - > frame = 0 ;
dma_q - > ini_jiffies = jiffies ;
2009-09-14 16:42:41 +04:00
init_waitqueue_head ( & dma_q - > wq ) ;
/* submit urbs and enables IRQ */
for ( i = 0 ; i < dev - > isoc_ctl . num_bufs ; i + + ) {
2008-04-09 08:49:19 +04:00
int rc = usb_submit_urb ( dev - > isoc_ctl . urb [ i ] , GFP_ATOMIC ) ;
2009-09-14 16:42:41 +04:00
if ( rc ) {
tm6000_err ( " submit of urb %i failed (error=%i) \n " , i ,
rc ) ;
tm6000_uninit_isoc ( dev ) ;
return rc ;
}
}
return 0 ;
}
/* ------------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* Videobuf operations
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2007-07-24 15:06:45 +04:00
2009-09-14 16:42:41 +04:00
static int
buffer_setup ( struct videobuf_queue * vq , unsigned int * count , unsigned int * size )
{
struct tm6000_fh * fh = vq - > priv_data ;
* size = fh - > fmt - > depth * fh - > width * fh - > height > > 3 ;
if ( 0 = = * count )
2007-07-24 15:06:45 +04:00
* count = TM6000_DEF_BUF ;
2010-10-20 13:35:12 +04:00
if ( * count < TM6000_MIN_BUF )
* count = TM6000_MIN_BUF ;
2007-07-24 15:06:45 +04:00
2009-09-14 16:42:41 +04:00
while ( * size * * count > vid_limit * 1024 * 1024 )
( * count ) - - ;
2007-07-24 15:06:45 +04:00
2009-09-14 16:42:41 +04:00
return 0 ;
}
static void free_buffer ( struct videobuf_queue * vq , struct tm6000_buffer * buf )
{
2008-10-26 15:18:53 +03:00
struct tm6000_fh * fh = vq - > priv_data ;
struct tm6000_core * dev = fh - > dev ;
unsigned long flags ;
2015-05-19 14:00:56 +03:00
BUG_ON ( in_interrupt ( ) ) ;
2009-09-14 16:42:41 +04:00
2008-10-26 15:18:53 +03:00
/* We used to wait for the buffer to finish here, but this didn't work
because , as we were keeping the state as VIDEOBUF_QUEUED ,
videobuf_queue_cancel marked it as finished for us .
( Also , it could wedge forever if the hardware was misconfigured . )
This should be safe ; by the time we get here , the buffer isn ' t
queued anymore . If we ever start marking the buffers as
VIDEOBUF_ACTIVE , it won ' t be , though .
*/
spin_lock_irqsave ( & dev - > slock , flags ) ;
if ( dev - > isoc_ctl . buf = = buf )
dev - > isoc_ctl . buf = NULL ;
spin_unlock_irqrestore ( & dev - > slock , flags ) ;
2009-09-14 16:42:41 +04:00
videobuf_vmalloc_free ( & buf - > vb ) ;
2007-11-15 22:37:35 +03:00
buf - > vb . state = VIDEOBUF_NEEDS_INIT ;
2009-09-14 16:42:41 +04:00
}
static int
buffer_prepare ( struct videobuf_queue * vq , struct videobuf_buffer * vb ,
enum v4l2_field field )
{
struct tm6000_fh * fh = vq - > priv_data ;
2010-10-20 13:35:12 +04:00
struct tm6000_buffer * buf = container_of ( vb , struct tm6000_buffer , vb ) ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2011-08-04 11:14:12 +04:00
int rc = 0 ;
2009-09-14 16:42:41 +04:00
BUG_ON ( NULL = = fh - > fmt ) ;
/* FIXME: It assumes depth=2 */
/* The only currently supported format is 16 bits/pixel */
buf - > vb . size = fh - > fmt - > depth * fh - > width * fh - > height > > 3 ;
if ( 0 ! = buf - > vb . baddr & & buf - > vb . bsize < buf - > vb . size )
return - EINVAL ;
if ( buf - > fmt ! = fh - > fmt | |
buf - > vb . width ! = fh - > width | |
buf - > vb . height ! = fh - > height | |
buf - > vb . field ! = field ) {
buf - > fmt = fh - > fmt ;
buf - > vb . width = fh - > width ;
buf - > vb . height = fh - > height ;
buf - > vb . field = field ;
2007-11-15 22:37:35 +03:00
buf - > vb . state = VIDEOBUF_NEEDS_INIT ;
2009-09-14 16:42:41 +04:00
}
2007-11-15 22:37:35 +03:00
if ( VIDEOBUF_NEEDS_INIT = = buf - > vb . state ) {
2011-06-02 06:21:56 +04:00
rc = videobuf_iolock ( vq , & buf - > vb , NULL ) ;
if ( rc ! = 0 )
2009-09-14 16:42:41 +04:00
goto fail ;
}
2011-08-04 11:14:12 +04:00
if ( ! dev - > isoc_ctl . num_bufs ) {
2011-02-18 04:11:05 +03:00
rc = tm6000_prepare_isoc ( dev ) ;
2008-04-09 08:49:19 +04:00
if ( rc < 0 )
goto fail ;
2008-01-10 23:27:26 +03:00
2008-04-09 08:49:19 +04:00
rc = tm6000_start_thread ( dev ) ;
2008-01-10 23:27:26 +03:00
if ( rc < 0 )
2009-09-14 16:42:41 +04:00
goto fail ;
2008-04-09 08:49:19 +04:00
2009-09-14 16:42:41 +04:00
}
2007-11-15 22:37:35 +03:00
buf - > vb . state = VIDEOBUF_PREPARED ;
2009-09-14 16:42:41 +04:00
return 0 ;
fail :
2008-01-10 23:27:26 +03:00
free_buffer ( vq , buf ) ;
2009-09-14 16:42:41 +04:00
return rc ;
}
static void
buffer_queue ( struct videobuf_queue * vq , struct videobuf_buffer * vb )
{
2010-10-20 13:35:12 +04:00
struct tm6000_buffer * buf = container_of ( vb , struct tm6000_buffer , vb ) ;
2009-09-14 16:42:41 +04:00
struct tm6000_fh * fh = vq - > priv_data ;
struct tm6000_core * dev = fh - > dev ;
struct tm6000_dmaqueue * vidq = & dev - > vidq ;
2008-04-09 08:49:19 +04:00
buf - > vb . state = VIDEOBUF_QUEUED ;
list_add_tail ( & buf - > vb . queue , & vidq - > active ) ;
2009-09-14 16:42:41 +04:00
}
static void buffer_release ( struct videobuf_queue * vq , struct videobuf_buffer * vb )
{
2010-10-20 13:35:12 +04:00
struct tm6000_buffer * buf = container_of ( vb , struct tm6000_buffer , vb ) ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
free_buffer ( vq , buf ) ;
2009-09-14 16:42:41 +04:00
}
2017-08-04 15:09:47 +03:00
static const struct videobuf_queue_ops tm6000_video_qops = {
2009-09-14 16:42:41 +04:00
. buf_setup = buffer_setup ,
. buf_prepare = buffer_prepare ,
. buf_queue = buffer_queue ,
. buf_release = buffer_release ,
} ;
/* ------------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* IOCTL handling
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-14 16:42:41 +04:00
2010-10-11 17:48:11 +04:00
static bool is_res_read ( struct tm6000_core * dev , struct tm6000_fh * fh )
2009-09-14 16:42:41 +04:00
{
2010-10-11 17:48:11 +04:00
/* Is the current fh handling it? if so, that's OK */
if ( dev - > resources = = fh & & dev - > is_res_read )
return true ;
return false ;
}
static bool is_res_streaming ( struct tm6000_core * dev , struct tm6000_fh * fh )
{
/* Is the current fh handling it? if so, that's OK */
if ( dev - > resources = = fh )
return true ;
return false ;
2009-09-14 16:42:41 +04:00
}
2010-10-11 17:48:11 +04:00
static bool res_get ( struct tm6000_core * dev , struct tm6000_fh * fh ,
bool is_res_read )
2009-09-14 16:42:41 +04:00
{
2010-10-11 17:48:11 +04:00
/* Is the current fh handling it? if so, that's OK */
if ( dev - > resources = = fh & & dev - > is_res_read = = is_res_read )
return true ;
/* is it free? */
if ( dev - > resources )
return false ;
/* grab it */
dev - > resources = fh ;
dev - > is_res_read = is_res_read ;
dprintk ( dev , V4L2_DEBUG_RES_LOCK , " res: get \n " ) ;
return true ;
2009-09-14 16:42:41 +04:00
}
static void res_free ( struct tm6000_core * dev , struct tm6000_fh * fh )
{
2010-10-11 17:48:11 +04:00
/* Is the current fh handling it? if so, that's OK */
if ( dev - > resources ! = fh )
return ;
dev - > resources = NULL ;
2009-09-14 16:42:41 +04:00
dprintk ( dev , V4L2_DEBUG_RES_LOCK , " res: put \n " ) ;
}
/* ------------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* IOCTL vidioc handling
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static int vidioc_querycap ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_capability * cap )
{
2011-05-09 23:53:50 +04:00
struct tm6000_core * dev = ( ( struct tm6000_fh * ) priv ) - > dev ;
2012-09-11 14:35:30 +04:00
struct video_device * vdev = video_devdata ( file ) ;
2009-09-14 16:42:41 +04:00
2018-09-10 15:19:14 +03:00
strscpy ( cap - > driver , " tm6000 " , sizeof ( cap - > driver ) ) ;
strscpy ( cap - > card , " Trident TVMaster TM5600/6000/6010 " ,
sizeof ( cap - > card ) ) ;
2012-09-11 14:35:30 +04:00
usb_make_path ( dev - > udev , cap - > bus_info , sizeof ( cap - > bus_info ) ) ;
2011-05-09 23:53:50 +04:00
if ( dev - > tuner_type ! = TUNER_ABSENT )
2012-09-11 14:35:30 +04:00
cap - > device_caps | = V4L2_CAP_TUNER ;
if ( vdev - > vfl_type = = VFL_TYPE_GRABBER )
cap - > device_caps | = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE ;
else
cap - > device_caps | = V4L2_CAP_RADIO ;
cap - > capabilities = cap - > device_caps | V4L2_CAP_DEVICE_CAPS |
V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE ;
2011-05-09 23:53:50 +04:00
2009-09-14 16:42:41 +04:00
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_enum_fmt_vid_cap ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_fmtdesc * f )
{
2012-09-11 14:35:30 +04:00
if ( f - > index > = ARRAY_SIZE ( format ) )
2009-09-14 16:42:41 +04:00
return - EINVAL ;
2018-09-10 15:19:14 +03:00
strscpy ( f - > description , format [ f - > index ] . name , sizeof ( f - > description ) ) ;
2009-09-14 16:42:41 +04:00
f - > pixelformat = format [ f - > index ] . fourcc ;
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_g_fmt_vid_cap ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_format * f )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
f - > fmt . pix . width = fh - > width ;
f - > fmt . pix . height = fh - > height ;
f - > fmt . pix . field = fh - > vb_vidq . field ;
f - > fmt . pix . pixelformat = fh - > fmt - > fourcc ;
2012-09-11 18:51:02 +04:00
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2009-09-14 16:42:41 +04:00
f - > fmt . pix . bytesperline =
( f - > fmt . pix . width * fh - > fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2010-10-20 13:35:12 +04:00
return 0 ;
2009-09-14 16:42:41 +04:00
}
2010-10-20 13:35:12 +04:00
static struct tm6000_fmt * format_by_fourcc ( unsigned int fourcc )
2009-09-14 16:42:41 +04:00
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( format ) ; i + + )
if ( format [ i ] . fourcc = = fourcc )
return format + i ;
return NULL ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_try_fmt_vid_cap ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_format * f )
{
struct tm6000_core * dev = ( ( struct tm6000_fh * ) priv ) - > dev ;
struct tm6000_fmt * fmt ;
enum v4l2_field field ;
fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
if ( NULL = = fmt ) {
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:19 +03:00
dprintk ( dev , 2 , " Fourcc format (0x%08x) invalid. \n " ,
f - > fmt . pix . pixelformat ) ;
2009-09-14 16:42:41 +04:00
return - EINVAL ;
}
field = f - > fmt . pix . field ;
2013-02-01 16:08:46 +04:00
field = V4L2_FIELD_INTERLACED ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
tm6000_get_std_res ( dev ) ;
2009-09-14 16:42:41 +04:00
2007-09-04 04:51:45 +04:00
f - > fmt . pix . width = dev - > width ;
f - > fmt . pix . height = dev - > height ;
2009-09-14 16:42:41 +04:00
f - > fmt . pix . width & = ~ 0x01 ;
f - > fmt . pix . field = field ;
f - > fmt . pix . bytesperline =
( f - > fmt . pix . width * fmt - > depth ) > > 3 ;
f - > fmt . pix . sizeimage =
f - > fmt . pix . height * f - > fmt . pix . bytesperline ;
2012-09-11 18:51:02 +04:00
f - > fmt . pix . colorspace = V4L2_COLORSPACE_SMPTE170M ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
/*FIXME: This seems to be generic enough to be at videodev2 */
2010-10-20 13:35:12 +04:00
static int vidioc_s_fmt_vid_cap ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_format * f )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2010-10-20 13:35:12 +04:00
int ret = vidioc_try_fmt_vid_cap ( file , fh , f ) ;
2009-09-14 16:42:41 +04:00
if ( ret < 0 )
2010-10-20 13:35:12 +04:00
return ret ;
2009-09-14 16:42:41 +04:00
fh - > fmt = format_by_fourcc ( f - > fmt . pix . pixelformat ) ;
fh - > width = f - > fmt . pix . width ;
fh - > height = f - > fmt . pix . height ;
fh - > vb_vidq . field = f - > fmt . pix . field ;
fh - > type = f - > type ;
dev - > fourcc = f - > fmt . pix . pixelformat ;
tm6000_set_fourcc_format ( dev ) ;
2010-10-20 13:35:12 +04:00
return 0 ;
2009-09-14 16:42:41 +04:00
}
2010-10-20 13:35:12 +04:00
static int vidioc_reqbufs ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_requestbuffers * p )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
return videobuf_reqbufs ( & fh - > vb_vidq , p ) ;
2009-09-14 16:42:41 +04:00
}
2010-10-20 13:35:12 +04:00
static int vidioc_querybuf ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_buffer * p )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
return videobuf_querybuf ( & fh - > vb_vidq , p ) ;
2009-09-14 16:42:41 +04:00
}
2010-10-20 13:35:12 +04:00
static int vidioc_qbuf ( struct file * file , void * priv , struct v4l2_buffer * p )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
return videobuf_qbuf ( & fh - > vb_vidq , p ) ;
2009-09-14 16:42:41 +04:00
}
2010-10-20 13:35:12 +04:00
static int vidioc_dqbuf ( struct file * file , void * priv , struct v4l2_buffer * p )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
return videobuf_dqbuf ( & fh - > vb_vidq , p ,
file - > f_flags & O_NONBLOCK ) ;
2009-09-14 16:42:41 +04:00
}
static int vidioc_streamon ( struct file * file , void * priv , enum v4l2_buf_type i )
{
2011-08-04 11:14:01 +04:00
struct tm6000_fh * fh = priv ;
struct tm6000_core * dev = fh - > dev ;
2009-09-14 16:42:41 +04:00
if ( fh - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
if ( i ! = fh - > type )
return - EINVAL ;
2010-10-11 17:48:11 +04:00
if ( ! res_get ( dev , fh , false ) )
2009-09-14 16:42:41 +04:00
return - EBUSY ;
2011-06-02 06:21:56 +04:00
return videobuf_streamon ( & fh - > vb_vidq ) ;
2009-09-14 16:42:41 +04:00
}
static int vidioc_streamoff ( struct file * file , void * priv , enum v4l2_buf_type i )
{
2011-08-04 11:14:01 +04:00
struct tm6000_fh * fh = priv ;
struct tm6000_core * dev = fh - > dev ;
2009-09-14 16:42:41 +04:00
if ( fh - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
return - EINVAL ;
2011-08-04 11:14:01 +04:00
2009-09-14 16:42:41 +04:00
if ( i ! = fh - > type )
return - EINVAL ;
videobuf_streamoff ( & fh - > vb_vidq ) ;
2011-06-02 06:21:56 +04:00
res_free ( dev , fh ) ;
2009-09-14 16:42:41 +04:00
2011-06-02 06:21:56 +04:00
return 0 ;
2009-09-14 16:42:41 +04:00
}
2013-03-15 13:10:40 +04:00
static int vidioc_s_std ( struct file * file , void * priv , v4l2_std_id norm )
2009-09-14 16:42:41 +04:00
{
2011-06-02 06:21:56 +04:00
int rc = 0 ;
2011-08-04 11:14:01 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2013-03-15 13:10:40 +04:00
dev - > norm = norm ;
2010-10-07 09:28:24 +04:00
rc = tm6000_init_analog_mode ( dev ) ;
2007-09-07 03:12:10 +04:00
fh - > width = dev - > width ;
fh - > height = dev - > height ;
2011-06-02 06:21:56 +04:00
if ( rc < 0 )
2009-09-14 16:42:41 +04:00
return rc ;
2014-04-28 23:53:01 +04:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , video , s_std , dev - > norm ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2013-06-03 12:36:44 +04:00
static int vidioc_g_std ( struct file * file , void * priv , v4l2_std_id * norm )
{
struct tm6000_fh * fh = priv ;
struct tm6000_core * dev = fh - > dev ;
* norm = dev - > norm ;
return 0 ;
}
2011-06-02 06:21:56 +04:00
static const char * iname [ ] = {
2011-05-09 23:53:52 +04:00
[ TM6000_INPUT_TV ] = " Television " ,
[ TM6000_INPUT_COMPOSITE1 ] = " Composite 1 " ,
[ TM6000_INPUT_COMPOSITE2 ] = " Composite 2 " ,
[ TM6000_INPUT_SVIDEO ] = " S-Video " ,
} ;
2010-10-20 13:35:12 +04:00
static int vidioc_enum_input ( struct file * file , void * priv ,
2011-05-09 23:53:52 +04:00
struct v4l2_input * i )
2009-09-14 16:42:41 +04:00
{
2011-03-18 03:08:55 +03:00
struct tm6000_fh * fh = priv ;
struct tm6000_core * dev = fh - > dev ;
2011-05-09 23:53:52 +04:00
unsigned int n ;
2011-03-18 03:08:55 +03:00
2011-05-09 23:53:52 +04:00
n = i - > index ;
if ( n > = 3 )
2009-09-14 16:42:41 +04:00
return - EINVAL ;
2011-05-09 23:53:52 +04:00
if ( ! dev - > vinput [ n ] . type )
return - EINVAL ;
i - > index = n ;
if ( dev - > vinput [ n ] . type = = TM6000_INPUT_TV )
i - > type = V4L2_INPUT_TYPE_TUNER ;
else
i - > type = V4L2_INPUT_TYPE_CAMERA ;
2018-09-10 23:20:42 +03:00
strscpy ( i - > name , iname [ dev - > vinput [ n ] . type ] , sizeof ( i - > name ) ) ;
2011-05-09 23:53:52 +04:00
i - > std = TM6000_STD ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_g_input ( struct file * file , void * priv , unsigned int * i )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2010-10-20 13:35:12 +04:00
* i = dev - > input ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2011-05-09 23:53:52 +04:00
2010-10-20 13:35:12 +04:00
static int vidioc_s_input ( struct file * file , void * priv , unsigned int i )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2010-10-20 13:35:12 +04:00
int rc = 0 ;
2009-09-14 16:42:41 +04:00
2011-05-09 23:53:52 +04:00
if ( i > = 3 )
return - EINVAL ;
if ( ! dev - > vinput [ i ] . type )
2009-09-14 16:42:41 +04:00
return - EINVAL ;
2011-05-09 23:53:52 +04:00
dev - > input = i ;
2013-06-03 12:36:44 +04:00
rc = vidioc_s_std ( file , priv , dev - > norm ) ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
return rc ;
2009-09-14 16:42:41 +04:00
}
2011-05-09 23:53:50 +04:00
/* --- controls ---------------------------------------------- */
2009-09-14 16:42:41 +04:00
2013-01-31 15:23:01 +04:00
static int tm6000_s_ctrl ( struct v4l2_ctrl * ctrl )
2009-09-14 16:42:41 +04:00
{
2013-01-31 15:23:01 +04:00
struct tm6000_core * dev = container_of ( ctrl - > handler , struct tm6000_core , ctrl_handler ) ;
u8 val = ctrl - > val ;
2009-09-14 16:42:41 +04:00
switch ( ctrl - > id ) {
case V4L2_CID_CONTRAST :
2013-01-31 15:23:01 +04:00
tm6000_set_reg ( dev , TM6010_REQ07_R08_LUMA_CONTRAST_ADJ , val ) ;
return 0 ;
2009-09-14 16:42:41 +04:00
case V4L2_CID_BRIGHTNESS :
2013-01-31 15:23:01 +04:00
tm6000_set_reg ( dev , TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ , val ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
case V4L2_CID_SATURATION :
2013-01-31 15:23:01 +04:00
tm6000_set_reg ( dev , TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ , val ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
case V4L2_CID_HUE :
2013-01-31 15:23:01 +04:00
tm6000_set_reg ( dev , TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ , val ) ;
2011-02-18 04:11:05 +03:00
return 0 ;
2009-09-14 16:42:41 +04:00
}
2013-01-31 15:23:01 +04:00
return - EINVAL ;
}
2009-09-14 16:42:41 +04:00
2013-01-31 15:23:01 +04:00
static const struct v4l2_ctrl_ops tm6000_ctrl_ops = {
. s_ctrl = tm6000_s_ctrl ,
} ;
2009-09-14 16:42:41 +04:00
2013-01-31 15:23:01 +04:00
static int tm6000_radio_s_ctrl ( struct v4l2_ctrl * ctrl )
2009-09-14 16:42:41 +04:00
{
2013-01-31 15:23:01 +04:00
struct tm6000_core * dev = container_of ( ctrl - > handler ,
struct tm6000_core , radio_ctrl_handler ) ;
u8 val = ctrl - > val ;
2009-09-14 16:42:41 +04:00
switch ( ctrl - > id ) {
2011-02-18 04:11:05 +03:00
case V4L2_CID_AUDIO_MUTE :
dev - > ctl_mute = val ;
tm6000_tvaudio_set_mute ( dev , val ) ;
return 0 ;
case V4L2_CID_AUDIO_VOLUME :
dev - > ctl_volume = val ;
tm6000_set_volume ( dev , val ) ;
return 0 ;
2009-09-14 16:42:41 +04:00
}
return - EINVAL ;
}
2013-01-31 15:23:01 +04:00
static const struct v4l2_ctrl_ops tm6000_radio_ctrl_ops = {
. s_ctrl = tm6000_radio_s_ctrl ,
} ;
2010-10-20 13:35:12 +04:00
static int vidioc_g_tuner ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_tuner * t )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2012-09-11 14:35:30 +04:00
if ( UNSET = = dev - > tuner_type )
return - ENOTTY ;
2009-09-14 16:42:41 +04:00
if ( 0 ! = t - > index )
return - EINVAL ;
2018-09-10 23:20:42 +03:00
strscpy ( t - > name , " Television " , sizeof ( t - > name ) ) ;
2009-09-14 16:42:41 +04:00
t - > type = V4L2_TUNER_ANALOG_TV ;
2012-09-11 14:35:30 +04:00
t - > capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO ;
2009-09-14 16:42:41 +04:00
t - > rangehigh = 0xffffffffUL ;
2011-05-09 23:53:50 +04:00
t - > rxsubchans = V4L2_TUNER_SUB_STEREO ;
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , g_tuner , t ) ;
t - > audmode = dev - > amode ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_s_tuner ( struct file * file , void * priv ,
2013-03-15 13:10:06 +04:00
const struct v4l2_tuner * t )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
if ( UNSET = = dev - > tuner_type )
2012-09-11 14:35:30 +04:00
return - ENOTTY ;
2009-09-14 16:42:41 +04:00
if ( 0 ! = t - > index )
return - EINVAL ;
2012-09-11 14:35:30 +04:00
if ( t - > audmode > V4L2_TUNER_MODE_STEREO )
dev - > amode = V4L2_TUNER_MODE_STEREO ;
else
dev - > amode = t - > audmode ;
2011-05-09 23:53:50 +04:00
dprintk ( dev , 3 , " audio mode: %x \n " , t - > audmode ) ;
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , s_tuner , t ) ;
2011-05-09 23:53:53 +04:00
2009-09-14 16:42:41 +04:00
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_g_frequency ( struct file * file , void * priv ,
2009-09-14 16:42:41 +04:00
struct v4l2_frequency * f )
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2012-09-11 14:35:30 +04:00
if ( UNSET = = dev - > tuner_type )
return - ENOTTY ;
if ( f - > tuner )
2009-09-14 16:42:41 +04:00
return - EINVAL ;
f - > frequency = dev - > freq ;
2009-09-14 23:37:13 +04:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , g_frequency , f ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2010-10-20 13:35:12 +04:00
static int vidioc_s_frequency ( struct file * file , void * priv ,
2013-03-19 11:09:26 +04:00
const struct v4l2_frequency * f )
2009-09-14 16:42:41 +04:00
{
2010-10-20 13:35:12 +04:00
struct tm6000_fh * fh = priv ;
2009-09-14 16:42:41 +04:00
struct tm6000_core * dev = fh - > dev ;
2012-09-11 14:35:30 +04:00
if ( UNSET = = dev - > tuner_type )
return - ENOTTY ;
if ( f - > tuner ! = 0 )
2011-02-18 04:11:05 +03:00
return - EINVAL ;
2009-09-14 16:42:41 +04:00
dev - > freq = f - > frequency ;
2009-09-15 00:16:32 +04:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , s_frequency , f ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
2011-02-18 04:11:05 +03:00
static int radio_g_tuner ( struct file * file , void * priv ,
struct v4l2_tuner * t )
{
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_core * dev = fh - > dev ;
if ( 0 ! = t - > index )
return - EINVAL ;
memset ( t , 0 , sizeof ( * t ) ) ;
2018-09-10 23:20:42 +03:00
strscpy ( t - > name , " Radio " , sizeof ( t - > name ) ) ;
2011-02-18 04:11:05 +03:00
t - > type = V4L2_TUNER_RADIO ;
2012-09-11 14:35:30 +04:00
t - > capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO ;
2011-05-09 23:53:50 +04:00
t - > rxsubchans = V4L2_TUNER_SUB_STEREO ;
2012-09-11 14:35:30 +04:00
t - > audmode = V4L2_TUNER_MODE_STEREO ;
2011-02-18 04:11:05 +03:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , g_tuner , t ) ;
return 0 ;
}
static int radio_s_tuner ( struct file * file , void * priv ,
2013-03-15 13:10:06 +04:00
const struct v4l2_tuner * t )
2011-02-18 04:11:05 +03:00
{
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_core * dev = fh - > dev ;
if ( 0 ! = t - > index )
return - EINVAL ;
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , s_tuner , t ) ;
return 0 ;
}
2009-09-14 16:42:41 +04:00
/* ------------------------------------------------------------------
File operations for the device
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-06-24 14:26:46 +04:00
static int __tm6000_open ( struct file * file )
2009-09-14 16:42:41 +04:00
{
2010-05-18 07:43:18 +04:00
struct video_device * vdev = video_devdata ( file ) ;
struct tm6000_core * dev = video_drvdata ( file ) ;
2009-09-14 16:42:41 +04:00
struct tm6000_fh * fh ;
2010-05-18 11:27:27 +04:00
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
2013-01-31 15:23:01 +04:00
int rc ;
2011-02-18 04:11:05 +03:00
int radio = 0 ;
2009-09-14 16:42:41 +04:00
2010-05-18 07:43:18 +04:00
dprintk ( dev , V4L2_DEBUG_OPEN , " tm6000: open called (dev=%s) \n " ,
video_device_node_name ( vdev ) ) ;
2009-09-14 16:42:41 +04:00
2011-02-18 04:11:05 +03:00
switch ( vdev - > vfl_type ) {
case VFL_TYPE_GRABBER :
type = V4L2_BUF_TYPE_VIDEO_CAPTURE ;
break ;
case VFL_TYPE_VBI :
type = V4L2_BUF_TYPE_VBI_CAPTURE ;
break ;
case VFL_TYPE_RADIO :
radio = 1 ;
break ;
2017-09-29 01:39:32 +03:00
default :
return - EINVAL ;
2011-02-18 04:11:05 +03:00
}
2009-09-14 16:42:41 +04:00
/* If more than one user, mutex should be added */
dev - > users + + ;
2010-05-18 07:43:18 +04:00
dprintk ( dev , V4L2_DEBUG_OPEN , " open dev=%s type=%s users=%d \n " ,
video_device_node_name ( vdev ) , v4l2_type_names [ type ] ,
dev - > users ) ;
2009-09-14 16:42:41 +04:00
/* allocate + initialize per filehandle data */
2010-10-20 13:35:12 +04:00
fh = kzalloc ( sizeof ( * fh ) , GFP_KERNEL ) ;
2009-09-14 16:42:41 +04:00
if ( NULL = = fh ) {
dev - > users - - ;
return - ENOMEM ;
}
2012-09-11 18:50:37 +04:00
v4l2_fh_init ( & fh - > fh , vdev ) ;
2009-09-14 16:42:41 +04:00
file - > private_data = fh ;
fh - > dev = dev ;
2011-02-18 04:11:05 +03:00
fh - > radio = radio ;
dev - > radio = radio ;
fh - > type = type ;
2009-09-14 16:42:41 +04:00
dev - > fourcc = format [ 0 ] . fourcc ;
fh - > fmt = format_by_fourcc ( dev - > fourcc ) ;
2007-09-04 04:51:45 +04:00
2011-06-02 06:21:56 +04:00
tm6000_get_std_res ( dev ) ;
2007-09-04 04:51:45 +04:00
2011-08-04 11:14:01 +04:00
fh - > width = dev - > width ;
fh - > height = dev - > height ;
2009-09-14 16:42:41 +04:00
2018-03-23 14:42:32 +03:00
dprintk ( dev , V4L2_DEBUG_OPEN , " Open: fh=%p, dev=%p, dev->vidq=%p \n " ,
fh , dev , & dev - > vidq ) ;
[media] tm6000: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:19 +03:00
dprintk ( dev , V4L2_DEBUG_OPEN , " Open: list_empty queued=%d \n " ,
list_empty ( & dev - > vidq . queued ) ) ;
dprintk ( dev , V4L2_DEBUG_OPEN , " Open: list_empty active=%d \n " ,
list_empty ( & dev - > vidq . active ) ) ;
2009-09-14 16:42:41 +04:00
/* initialize hardware on analog mode */
2010-10-12 19:11:55 +04:00
rc = tm6000_init_analog_mode ( dev ) ;
2016-12-19 20:10:58 +03:00
if ( rc < 0 ) {
v4l2_fh_exit ( & fh - > fh ) ;
kfree ( fh ) ;
2010-10-12 19:11:55 +04:00
return rc ;
2016-12-19 20:10:58 +03:00
}
2009-09-14 16:42:41 +04:00
2013-01-31 15:23:01 +04:00
dev - > mode = TM6000_MODE_ANALOG ;
2009-09-14 16:42:41 +04:00
2011-08-04 11:14:15 +04:00
if ( ! fh - > radio ) {
videobuf_queue_vmalloc_init ( & fh - > vb_vidq , & tm6000_video_qops ,
NULL , & dev - > slock ,
fh - > type ,
V4L2_FIELD_INTERLACED ,
sizeof ( struct tm6000_buffer ) , fh , & dev - > lock ) ;
} else {
2011-02-18 04:11:05 +03:00
dprintk ( dev , V4L2_DEBUG_OPEN , " video_open: setting radio device \n " ) ;
2011-05-09 23:53:53 +04:00
tm6000_set_audio_rinput ( dev ) ;
2011-02-18 04:11:05 +03:00
v4l2_device_call_all ( & dev - > v4l2_dev , 0 , tuner , s_radio ) ;
tm6000_prepare_isoc ( dev ) ;
tm6000_start_thread ( dev ) ;
}
2012-09-11 18:50:37 +04:00
v4l2_fh_add ( & fh - > fh ) ;
2011-02-18 04:11:05 +03:00
2009-09-14 16:42:41 +04:00
return 0 ;
}
2012-06-24 14:26:46 +04:00
static int tm6000_open ( struct file * file )
{
struct video_device * vdev = video_devdata ( file ) ;
int res ;
mutex_lock ( vdev - > lock ) ;
res = __tm6000_open ( file ) ;
mutex_unlock ( vdev - > lock ) ;
return res ;
}
2009-09-14 16:42:41 +04:00
static ssize_t
tm6000_read ( struct file * file , char __user * data , size_t count , loff_t * pos )
{
2012-06-24 14:26:46 +04:00
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_core * dev = fh - > dev ;
2009-09-14 16:42:41 +04:00
2011-06-02 06:21:56 +04:00
if ( fh - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE ) {
2012-06-24 14:26:46 +04:00
int res ;
2010-10-11 17:48:11 +04:00
if ( ! res_get ( fh - > dev , fh , true ) )
2009-09-14 16:42:41 +04:00
return - EBUSY ;
2012-06-24 14:26:46 +04:00
if ( mutex_lock_interruptible ( & dev - > lock ) )
return - ERESTARTSYS ;
res = videobuf_read_stream ( & fh - > vb_vidq , data , count , pos , 0 ,
2009-09-14 16:42:41 +04:00
file - > f_flags & O_NONBLOCK ) ;
2012-06-24 14:26:46 +04:00
mutex_unlock ( & dev - > lock ) ;
return res ;
2009-09-14 16:42:41 +04:00
}
return 0 ;
}
2017-07-03 10:02:56 +03:00
static __poll_t
2012-06-24 14:26:46 +04:00
__tm6000_poll ( struct file * file , struct poll_table_struct * wait )
2009-09-14 16:42:41 +04:00
{
2017-07-03 10:14:15 +03:00
__poll_t req_events = poll_requested_events ( wait ) ;
2009-09-14 16:42:41 +04:00
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_buffer * buf ;
2017-07-03 10:02:56 +03:00
__poll_t res = 0 ;
2009-09-14 16:42:41 +04:00
2012-09-11 18:50:37 +04:00
if ( v4l2_event_pending ( & fh - > fh ) )
2018-02-12 01:34:03 +03:00
res = EPOLLPRI ;
else if ( req_events & EPOLLPRI )
2012-09-11 18:50:37 +04:00
poll_wait ( file , & fh - > fh . wait , wait ) ;
2009-09-14 16:42:41 +04:00
if ( V4L2_BUF_TYPE_VIDEO_CAPTURE ! = fh - > type )
2018-02-12 01:34:03 +03:00
return res | EPOLLERR ;
2009-09-14 16:42:41 +04:00
2010-10-11 17:48:11 +04:00
if ( ! ! is_res_streaming ( fh - > dev , fh ) )
2018-02-12 01:34:03 +03:00
return res | EPOLLERR ;
2010-10-11 17:48:11 +04:00
if ( ! is_res_read ( fh - > dev , fh ) ) {
2009-09-14 16:42:41 +04:00
/* streaming capture */
if ( list_empty ( & fh - > vb_vidq . stream ) )
2018-02-12 01:34:03 +03:00
return res | EPOLLERR ;
2011-06-02 06:21:56 +04:00
buf = list_entry ( fh - > vb_vidq . stream . next , struct tm6000_buffer , vb . stream ) ;
2013-02-07 14:05:43 +04:00
poll_wait ( file , & buf - > vb . done , wait ) ;
if ( buf - > vb . state = = VIDEOBUF_DONE | |
buf - > vb . state = = VIDEOBUF_ERROR )
2018-02-12 01:34:03 +03:00
return res | EPOLLIN | EPOLLRDNORM ;
} else if ( req_events & ( EPOLLIN | EPOLLRDNORM ) ) {
2009-09-14 16:42:41 +04:00
/* read() capture */
2012-09-11 18:50:37 +04:00
return res | videobuf_poll_stream ( file , & fh - > vb_vidq , wait ) ;
2009-09-14 16:42:41 +04:00
}
2012-09-11 18:50:37 +04:00
return res ;
2009-09-14 16:42:41 +04:00
}
2017-07-03 10:02:56 +03:00
static __poll_t tm6000_poll ( struct file * file , struct poll_table_struct * wait )
2012-06-24 14:26:46 +04:00
{
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_core * dev = fh - > dev ;
2017-07-03 10:02:56 +03:00
__poll_t res ;
2012-06-24 14:26:46 +04:00
mutex_lock ( & dev - > lock ) ;
res = __tm6000_poll ( file , wait ) ;
mutex_unlock ( & dev - > lock ) ;
return res ;
}
2009-09-15 00:16:32 +04:00
static int tm6000_release ( struct file * file )
2009-09-14 16:42:41 +04:00
{
struct tm6000_fh * fh = file - > private_data ;
struct tm6000_core * dev = fh - > dev ;
2010-05-18 07:43:18 +04:00
struct video_device * vdev = video_devdata ( file ) ;
2009-09-14 16:42:41 +04:00
2010-05-18 07:43:18 +04:00
dprintk ( dev , V4L2_DEBUG_OPEN , " tm6000: close called (dev=%s, users=%d) \n " ,
video_device_node_name ( vdev ) , dev - > users ) ;
2007-06-17 06:21:48 +04:00
2012-06-24 14:26:46 +04:00
mutex_lock ( & dev - > lock ) ;
2007-06-18 00:14:12 +04:00
dev - > users - - ;
2010-10-11 17:48:11 +04:00
res_free ( dev , fh ) ;
2011-08-04 11:14:13 +04:00
2007-06-18 00:14:12 +04:00
if ( ! dev - > users ) {
2008-04-09 08:49:19 +04:00
tm6000_uninit_isoc ( dev ) ;
2011-08-04 11:14:15 +04:00
2011-11-28 22:46:18 +04:00
/* Stop interrupt USB pipe */
tm6000_ir_int_stop ( dev ) ;
usb_reset_configuration ( dev - > udev ) ;
2011-12-06 16:39:35 +04:00
if ( dev - > int_in . endp )
2011-11-28 22:46:18 +04:00
usb_set_interface ( dev - > udev ,
2011-12-06 16:39:36 +04:00
dev - > isoc_in . bInterfaceNumber , 2 ) ;
2011-11-28 22:46:18 +04:00
else
usb_set_interface ( dev - > udev ,
2011-12-06 16:39:36 +04:00
dev - > isoc_in . bInterfaceNumber , 0 ) ;
2011-11-28 22:46:18 +04:00
/* Start interrupt USB pipe */
tm6000_ir_int_start ( dev ) ;
2011-08-04 11:14:15 +04:00
if ( ! fh - > radio )
videobuf_mmap_free ( & fh - > vb_vidq ) ;
2007-06-18 00:14:12 +04:00
}
2012-09-11 18:50:37 +04:00
v4l2_fh_del ( & fh - > fh ) ;
v4l2_fh_exit ( & fh - > fh ) ;
2010-10-20 13:35:12 +04:00
kfree ( fh ) ;
2012-06-24 14:26:46 +04:00
mutex_unlock ( & dev - > lock ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
static int tm6000_mmap ( struct file * file , struct vm_area_struct * vma )
{
2011-08-04 11:14:01 +04:00
struct tm6000_fh * fh = file - > private_data ;
2012-06-24 14:26:46 +04:00
struct tm6000_core * dev = fh - > dev ;
int res ;
2009-09-14 16:42:41 +04:00
2012-06-24 14:26:46 +04:00
if ( mutex_lock_interruptible ( & dev - > lock ) )
return - ERESTARTSYS ;
res = videobuf_mmap_mapper ( & fh - > vb_vidq , vma ) ;
mutex_unlock ( & dev - > lock ) ;
return res ;
2009-09-14 16:42:41 +04:00
}
2017-06-29 09:55:23 +03:00
static const struct v4l2_file_operations tm6000_fops = {
2011-08-04 11:14:01 +04:00
. owner = THIS_MODULE ,
. open = tm6000_open ,
. release = tm6000_release ,
. unlocked_ioctl = video_ioctl2 , /* V4L2 ioctl handler */
. read = tm6000_read ,
. poll = tm6000_poll ,
. mmap = tm6000_mmap ,
2009-09-14 16:42:41 +04:00
} ;
2008-10-25 17:43:04 +04:00
static const struct v4l2_ioctl_ops video_ioctl_ops = {
. vidioc_querycap = vidioc_querycap ,
. vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap ,
. vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap ,
. vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap ,
. vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap ,
. vidioc_s_std = vidioc_s_std ,
2013-06-03 12:36:44 +04:00
. vidioc_g_std = vidioc_g_std ,
2008-10-25 17:43:04 +04:00
. vidioc_enum_input = vidioc_enum_input ,
. vidioc_g_input = vidioc_g_input ,
. vidioc_s_input = vidioc_s_input ,
. vidioc_g_tuner = vidioc_g_tuner ,
. vidioc_s_tuner = vidioc_s_tuner ,
. vidioc_g_frequency = vidioc_g_frequency ,
. vidioc_s_frequency = vidioc_s_frequency ,
. vidioc_streamon = vidioc_streamon ,
. vidioc_streamoff = vidioc_streamoff ,
. vidioc_reqbufs = vidioc_reqbufs ,
. vidioc_querybuf = vidioc_querybuf ,
. vidioc_qbuf = vidioc_qbuf ,
. vidioc_dqbuf = vidioc_dqbuf ,
2012-09-11 18:50:37 +04:00
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2008-10-25 17:43:04 +04:00
} ;
2009-09-14 16:42:41 +04:00
static struct video_device tm6000_template = {
. name = " tm6000 " ,
. fops = & tm6000_fops ,
2008-10-25 17:43:04 +04:00
. ioctl_ops = & video_ioctl_ops ,
2015-03-09 19:34:10 +03:00
. release = video_device_release_empty ,
2008-10-25 17:43:04 +04:00
. tvnorms = TM6000_STD ,
2009-09-14 16:42:41 +04:00
} ;
2008-10-25 17:43:04 +04:00
2011-02-18 04:11:05 +03:00
static const struct v4l2_file_operations radio_fops = {
2011-05-09 23:54:01 +04:00
. owner = THIS_MODULE ,
. open = tm6000_open ,
2012-09-11 18:53:51 +04:00
. poll = v4l2_ctrl_poll ,
2011-05-09 23:54:01 +04:00
. release = tm6000_release ,
. unlocked_ioctl = video_ioctl2 ,
2011-02-18 04:11:05 +03:00
} ;
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
2012-09-11 14:35:30 +04:00
. vidioc_querycap = vidioc_querycap ,
2011-02-18 04:11:05 +03:00
. vidioc_g_tuner = radio_g_tuner ,
. vidioc_s_tuner = radio_s_tuner ,
. vidioc_g_frequency = vidioc_g_frequency ,
. vidioc_s_frequency = vidioc_s_frequency ,
2012-09-11 18:50:37 +04:00
. vidioc_subscribe_event = v4l2_ctrl_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2011-02-18 04:11:05 +03:00
} ;
2011-08-04 11:14:01 +04:00
static struct video_device tm6000_radio_template = {
2011-02-18 04:11:05 +03:00
. name = " tm6000 " ,
. fops = & radio_fops ,
2011-06-02 06:21:56 +04:00
. ioctl_ops = & radio_ioctl_ops ,
2011-02-18 04:11:05 +03:00
} ;
2009-09-14 16:42:41 +04:00
/* -----------------------------------------------------------------
2010-10-20 13:35:12 +04:00
* Initialization and module stuff
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2009-09-14 16:42:41 +04:00
2015-03-09 19:34:10 +03:00
static void vdev_init ( struct tm6000_core * dev ,
struct video_device * vfd ,
2011-01-13 06:46:07 +03:00
const struct video_device
* template , const char * type_name )
2009-09-14 16:42:41 +04:00
{
2011-01-13 06:46:07 +03:00
* vfd = * template ;
vfd - > v4l2_dev = & dev - > v4l2_dev ;
2015-03-09 19:34:10 +03:00
vfd - > release = video_device_release_empty ;
2011-01-13 06:46:07 +03:00
vfd - > lock = & dev - > lock ;
snprintf ( vfd - > name , sizeof ( vfd - > name ) , " %s %s " , dev - > name , type_name ) ;
video_set_drvdata ( vfd , dev ) ;
}
int tm6000_v4l2_register ( struct tm6000_core * dev )
{
2013-01-31 15:23:01 +04:00
int ret = 0 ;
v4l2_ctrl_handler_init ( & dev - > ctrl_handler , 6 ) ;
v4l2_ctrl_handler_init ( & dev - > radio_ctrl_handler , 2 ) ;
v4l2_ctrl_new_std ( & dev - > radio_ctrl_handler , & tm6000_radio_ctrl_ops ,
V4L2_CID_AUDIO_MUTE , 0 , 1 , 1 , 0 ) ;
v4l2_ctrl_new_std ( & dev - > radio_ctrl_handler , & tm6000_radio_ctrl_ops ,
V4L2_CID_AUDIO_VOLUME , - 15 , 15 , 1 , 0 ) ;
v4l2_ctrl_new_std ( & dev - > ctrl_handler , & tm6000_ctrl_ops ,
V4L2_CID_BRIGHTNESS , 0 , 255 , 1 , 54 ) ;
v4l2_ctrl_new_std ( & dev - > ctrl_handler , & tm6000_ctrl_ops ,
V4L2_CID_CONTRAST , 0 , 255 , 1 , 119 ) ;
v4l2_ctrl_new_std ( & dev - > ctrl_handler , & tm6000_ctrl_ops ,
V4L2_CID_SATURATION , 0 , 255 , 1 , 112 ) ;
v4l2_ctrl_new_std ( & dev - > ctrl_handler , & tm6000_ctrl_ops ,
V4L2_CID_HUE , - 128 , 127 , 1 , 0 ) ;
v4l2_ctrl_add_handler ( & dev - > ctrl_handler ,
2018-05-21 11:54:36 +03:00
& dev - > radio_ctrl_handler , NULL , false ) ;
2013-01-31 15:23:01 +04:00
if ( dev - > radio_ctrl_handler . error )
ret = dev - > radio_ctrl_handler . error ;
if ( ! ret & & dev - > ctrl_handler . error )
ret = dev - > ctrl_handler . error ;
if ( ret )
goto free_ctrl ;
2011-01-13 06:46:07 +03:00
2015-03-09 19:34:10 +03:00
vdev_init ( dev , & dev - > vfd , & tm6000_template , " video " ) ;
2011-01-13 06:46:07 +03:00
2015-03-09 19:34:10 +03:00
dev - > vfd . ctrl_handler = & dev - > ctrl_handler ;
2009-09-14 16:42:41 +04:00
/* init video dma queues */
INIT_LIST_HEAD ( & dev - > vidq . active ) ;
INIT_LIST_HEAD ( & dev - > vidq . queued ) ;
2015-03-09 19:34:10 +03:00
ret = video_register_device ( & dev - > vfd , VFL_TYPE_GRABBER , video_nr ) ;
2010-10-10 00:05:14 +04:00
2011-01-13 06:46:07 +03:00
if ( ret < 0 ) {
printk ( KERN_INFO " %s: can't register video device \n " ,
dev - > name ) ;
2013-01-31 15:23:01 +04:00
goto free_ctrl ;
2011-01-13 06:46:07 +03:00
}
printk ( KERN_INFO " %s: registered device %s \n " ,
2015-03-09 19:34:10 +03:00
dev - > name , video_device_node_name ( & dev - > vfd ) ) ;
2009-09-14 16:42:41 +04:00
2011-05-09 23:53:49 +04:00
if ( dev - > caps . has_radio ) {
2015-03-09 19:34:10 +03:00
vdev_init ( dev , & dev - > radio_dev , & tm6000_radio_template ,
2011-05-09 23:53:49 +04:00
" radio " ) ;
2015-03-09 19:34:10 +03:00
dev - > radio_dev . ctrl_handler = & dev - > radio_ctrl_handler ;
ret = video_register_device ( & dev - > radio_dev , VFL_TYPE_RADIO ,
2011-05-09 23:53:49 +04:00
radio_nr ) ;
if ( ret < 0 ) {
printk ( KERN_INFO " %s: can't register radio device \n " ,
dev - > name ) ;
2013-01-31 15:23:01 +04:00
goto unreg_video ;
2011-05-09 23:53:49 +04:00
}
2011-02-18 04:11:05 +03:00
2011-05-09 23:53:49 +04:00
printk ( KERN_INFO " %s: registered device %s \n " ,
2015-03-09 19:34:10 +03:00
dev - > name , video_device_node_name ( & dev - > radio_dev ) ) ;
2011-05-09 23:53:49 +04:00
}
2011-02-18 04:11:05 +03:00
2010-02-22 12:32:15 +03:00
printk ( KERN_INFO " Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d) \n " , ret ) ;
2009-09-14 16:42:41 +04:00
return ret ;
2013-01-31 15:23:01 +04:00
unreg_video :
2015-03-09 19:34:10 +03:00
video_unregister_device ( & dev - > vfd ) ;
2013-01-31 15:23:01 +04:00
free_ctrl :
v4l2_ctrl_handler_free ( & dev - > ctrl_handler ) ;
v4l2_ctrl_handler_free ( & dev - > radio_ctrl_handler ) ;
return ret ;
2009-09-14 16:42:41 +04:00
}
int tm6000_v4l2_unregister ( struct tm6000_core * dev )
{
2015-03-09 19:34:10 +03:00
video_unregister_device ( & dev - > vfd ) ;
2007-06-15 00:19:59 +04:00
2012-10-04 17:04:28 +04:00
/* if URB buffers are still allocated free them now */
tm6000_free_urb_buffers ( dev ) ;
2015-03-09 19:34:10 +03:00
video_unregister_device ( & dev - > radio_dev ) ;
2009-09-14 16:42:41 +04:00
return 0 ;
}
int tm6000_v4l2_exit ( void )
{
return 0 ;
}
module_param ( video_nr , int , 0 ) ;
2010-10-20 13:35:12 +04:00
MODULE_PARM_DESC ( video_nr , " Allow changing video device number " ) ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
module_param_named ( debug , tm6000_debug , int , 0444 ) ;
MODULE_PARM_DESC ( debug , " activates debug info " ) ;
2009-09-14 16:42:41 +04:00
2010-10-20 13:35:12 +04:00
module_param ( vid_limit , int , 0644 ) ;
MODULE_PARM_DESC ( vid_limit , " capture memory limit in megabytes " ) ;
2009-09-14 16:42:41 +04:00
2012-10-04 17:04:28 +04:00
module_param ( keep_urb , bool , 0 ) ;
MODULE_PARM_DESC ( keep_urb , " Keep urb buffers allocated even when the device is closed by the user " ) ;