2019-05-31 11:09:32 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-02-28 06:43:04 +03:00
/*
2015-01-20 11:20:50 +03:00
* Line 6 Linux USB driver
2009-02-28 06:43:04 +03:00
*
2010-08-12 03:35:30 +04:00
* Copyright ( C ) 2004 - 2010 Markus Grabner ( grabner @ icg . tugraz . at )
2009-02-28 06:43:04 +03:00
*/
2011-11-23 12:20:45 +04:00
# include <linux/slab.h>
2009-02-28 06:43:04 +03:00
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
2010-08-12 03:35:30 +04:00
# include "capture.h"
# include "driver.h"
2009-02-28 06:43:04 +03:00
# include "pcm.h"
2009-02-28 07:45:03 +03:00
# include "playback.h"
2009-02-28 06:43:04 +03:00
/*
Software stereo volume control .
*/
2009-02-28 09:41:12 +03:00
static void change_volume ( struct urb * urb_out , int volume [ ] ,
int bytes_per_frame )
2009-02-28 06:43:04 +03:00
{
int chn = 0 ;
2009-02-28 09:41:12 +03:00
if ( volume [ 0 ] = = 256 & & volume [ 1 ] = = 256 )
2009-11-16 07:17:50 +03:00
return ; /* maximum volume - no change */
2009-02-28 06:43:04 +03:00
2009-02-28 09:41:12 +03:00
if ( bytes_per_frame = = 4 ) {
2015-01-28 14:29:05 +03:00
__le16 * p , * buf_end ;
2014-03-25 02:46:31 +04:00
2015-01-28 14:29:05 +03:00
p = ( __le16 * ) urb_out - > transfer_buffer ;
2009-02-28 06:43:04 +03:00
buf_end = p + urb_out - > transfer_buffer_length / sizeof ( * p ) ;
2009-02-28 09:41:12 +03:00
for ( ; p < buf_end ; + + p ) {
2015-01-28 14:29:05 +03:00
short pv = le16_to_cpu ( * p ) ;
int val = ( pv * volume [ chn & 1 ] ) > > 8 ;
2015-03-05 15:03:28 +03:00
pv = clamp ( val , - 0x8000 , 0x7fff ) ;
2015-01-28 14:29:05 +03:00
* p = cpu_to_le16 ( pv ) ;
2009-02-28 06:43:04 +03:00
+ + chn ;
}
2009-02-28 09:41:12 +03:00
} else if ( bytes_per_frame = = 6 ) {
2009-02-28 06:43:04 +03:00
unsigned char * p , * buf_end ;
2014-04-24 11:31:48 +04:00
2009-02-28 06:43:04 +03:00
p = ( unsigned char * ) urb_out - > transfer_buffer ;
buf_end = p + urb_out - > transfer_buffer_length ;
2009-02-28 09:41:12 +03:00
for ( ; p < buf_end ; p + = 3 ) {
int val ;
2014-03-25 02:46:31 +04:00
2009-02-28 09:41:12 +03:00
val = p [ 0 ] + ( p [ 1 ] < < 8 ) + ( ( signed char ) p [ 2 ] < < 16 ) ;
2009-02-28 06:43:04 +03:00
val = ( val * volume [ chn & 1 ] ) > > 8 ;
2015-03-05 15:03:28 +03:00
val = clamp ( val , - 0x800000 , 0x7fffff ) ;
2009-02-28 06:43:04 +03:00
p [ 0 ] = val ;
p [ 1 ] = val > > 8 ;
p [ 2 ] = val > > 16 ;
+ + chn ;
}
}
}
2010-08-12 03:35:30 +04:00
/*
Create signal for impulse response test .
*/
static void create_impulse_test_signal ( struct snd_line6_pcm * line6pcm ,
struct urb * urb_out , int bytes_per_frame )
{
int frames = urb_out - > transfer_buffer_length / bytes_per_frame ;
if ( bytes_per_frame = = 4 ) {
2010-08-23 03:08:25 +04:00
int i ;
short * pi = ( short * ) line6pcm - > prev_fbuf ;
short * po = ( short * ) urb_out - > transfer_buffer ;
for ( i = 0 ; i < frames ; + + i ) {
po [ 0 ] = pi [ 0 ] ;
po [ 1 ] = 0 ;
pi + = 2 ;
po + = 2 ;
}
2010-08-12 03:35:30 +04:00
} else if ( bytes_per_frame = = 6 ) {
int i , j ;
unsigned char * pi = line6pcm - > prev_fbuf ;
unsigned char * po = urb_out - > transfer_buffer ;
for ( i = 0 ; i < frames ; + + i ) {
for ( j = 0 ; j < bytes_per_frame / 2 ; + + j )
po [ j ] = pi [ j ] ;
for ( ; j < bytes_per_frame ; + + j )
po [ j ] = 0 ;
pi + = bytes_per_frame ;
po + = bytes_per_frame ;
}
2010-08-23 03:08:25 +04:00
}
if ( - - line6pcm - > impulse_count < = 0 ) {
( ( unsigned char * ) ( urb_out - > transfer_buffer ) ) [ bytes_per_frame -
1 ] =
line6pcm - > impulse_volume ;
line6pcm - > impulse_count = line6pcm - > impulse_period ;
2010-08-12 03:35:30 +04:00
}
}
/*
Add signal to buffer for software monitoring .
*/
static void add_monitor_signal ( struct urb * urb_out , unsigned char * signal ,
int volume , int bytes_per_frame )
{
if ( volume = = 0 )
return ; /* zero volume - no change */
if ( bytes_per_frame = = 4 ) {
2015-01-28 14:29:05 +03:00
__le16 * pi , * po , * buf_end ;
2014-03-25 02:46:31 +04:00
2015-01-28 14:29:05 +03:00
pi = ( __le16 * ) signal ;
po = ( __le16 * ) urb_out - > transfer_buffer ;
2010-08-12 03:35:30 +04:00
buf_end = po + urb_out - > transfer_buffer_length / sizeof ( * po ) ;
2015-01-23 18:54:36 +03:00
for ( ; po < buf_end ; + + pi , + + po ) {
2015-01-28 14:29:05 +03:00
short pov = le16_to_cpu ( * po ) ;
short piv = le16_to_cpu ( * pi ) ;
int val = pov + ( ( piv * volume ) > > 8 ) ;
2015-03-05 15:03:28 +03:00
pov = clamp ( val , - 0x8000 , 0x7fff ) ;
2015-01-28 14:29:05 +03:00
* po = cpu_to_le16 ( pov ) ;
2015-01-23 18:54:36 +03:00
}
2010-08-12 03:35:30 +04:00
}
/*
2010-08-23 03:08:25 +04:00
We don ' t need to handle devices with 6 bytes per frame here
since they all support hardware monitoring .
*/
2010-08-12 03:35:30 +04:00
}
2009-02-28 06:43:04 +03:00
/*
Find a free URB , prepare audio data , and submit URB .
2015-01-27 14:50:44 +03:00
must be called in line6pcm - > out . lock context
2009-02-28 06:43:04 +03:00
*/
2010-08-12 03:35:30 +04:00
static int submit_audio_out_urb ( struct snd_line6_pcm * line6pcm )
2009-02-28 06:43:04 +03:00
{
int index ;
int i , urb_size , urb_frames ;
2010-08-23 03:08:25 +04:00
int ret ;
2016-09-18 21:59:24 +03:00
const int bytes_per_frame =
line6pcm - > properties - > bytes_per_channel *
line6pcm - > properties - > playback_hw . channels_max ;
2009-11-16 07:17:50 +03:00
const int frame_increment =
2015-01-28 17:08:59 +03:00
line6pcm - > properties - > rates . rats [ 0 ] . num_min ;
2009-11-16 07:17:50 +03:00
const int frame_factor =
2015-01-28 17:08:59 +03:00
line6pcm - > properties - > rates . rats [ 0 ] . den *
2016-09-18 21:59:22 +03:00
( line6pcm - > line6 - > intervals_per_second / LINE6_ISO_INTERVAL ) ;
2009-02-28 06:43:04 +03:00
struct urb * urb_out ;
2016-09-18 21:59:21 +03:00
index = find_first_zero_bit ( & line6pcm - > out . active_urbs ,
line6pcm - > line6 - > iso_buffers ) ;
2009-02-28 06:43:04 +03:00
2016-09-18 21:59:21 +03:00
if ( index < 0 | | index > = line6pcm - > line6 - > iso_buffers ) {
2010-08-12 03:35:30 +04:00
dev_err ( line6pcm - > line6 - > ifcdev , " no free URB found \n " ) ;
2009-02-28 06:43:04 +03:00
return - EINVAL ;
}
2015-01-23 18:10:57 +03:00
urb_out = line6pcm - > out . urbs [ index ] ;
2009-02-28 06:43:04 +03:00
urb_size = 0 ;
2016-09-18 21:59:24 +03:00
/* TODO: this may not work for LINE6_ISO_PACKETS != 1 */
2009-02-28 09:41:12 +03:00
for ( i = 0 ; i < LINE6_ISO_PACKETS ; + + i ) {
2009-02-28 06:43:04 +03:00
/* compute frame size for given sampling rate */
2010-08-12 03:35:30 +04:00
int fsize = 0 ;
2009-11-16 07:17:50 +03:00
struct usb_iso_packet_descriptor * fout =
& urb_out - > iso_frame_desc [ i ] ;
2010-08-12 03:35:30 +04:00
2015-01-27 18:17:26 +03:00
fsize = line6pcm - > prev_fsize ;
2010-08-12 03:35:30 +04:00
if ( fsize = = 0 ) {
int n ;
2014-03-25 02:46:31 +04:00
2015-01-23 18:10:57 +03:00
line6pcm - > out . count + = frame_increment ;
n = line6pcm - > out . count / frame_factor ;
line6pcm - > out . count - = n * frame_factor ;
2016-09-18 21:59:24 +03:00
fsize = n ;
2010-08-12 03:35:30 +04:00
}
2016-09-18 21:59:24 +03:00
fsize * = bytes_per_frame ;
2009-02-28 06:43:04 +03:00
fout - > offset = urb_size ;
2010-08-12 03:35:30 +04:00
fout - > length = fsize ;
urb_size + = fsize ;
}
if ( urb_size = = 0 ) {
/* can't determine URB size */
2012-11-11 16:24:43 +04:00
dev_err ( line6pcm - > line6 - > ifcdev , " driver bug: urb_size = 0 \n " ) ;
2010-08-12 03:35:30 +04:00
return - EINVAL ;
2009-02-28 06:43:04 +03:00
}
urb_frames = urb_size / bytes_per_frame ;
2010-08-12 03:35:30 +04:00
urb_out - > transfer_buffer =
2015-01-23 18:10:57 +03:00
line6pcm - > out . buffer +
2016-09-18 21:59:23 +03:00
index * LINE6_ISO_PACKETS * line6pcm - > max_packet_size_out ;
2010-08-12 03:35:30 +04:00
urb_out - > transfer_buffer_length = urb_size ;
urb_out - > context = line6pcm ;
2015-01-27 17:24:09 +03:00
if ( test_bit ( LINE6_STREAM_PCM , & line6pcm - > out . running ) & &
! test_bit ( LINE6_FLAG_PAUSE_PLAYBACK , & line6pcm - > flags ) ) {
2010-08-12 03:35:30 +04:00
struct snd_pcm_runtime * runtime =
get_substream ( line6pcm , SNDRV_PCM_STREAM_PLAYBACK ) - > runtime ;
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
if ( line6pcm - > out . pos + urb_frames > runtime - > buffer_size ) {
2009-02-28 06:43:04 +03:00
/*
2009-11-16 07:17:50 +03:00
The transferred area goes over buffer boundary ,
copy the data to the temp buffer .
*/
2009-02-28 06:43:04 +03:00
int len ;
2014-03-25 02:46:31 +04:00
2015-01-23 18:10:57 +03:00
len = runtime - > buffer_size - line6pcm - > out . pos ;
2009-02-28 06:43:04 +03:00
2009-02-28 09:41:12 +03:00
if ( len > 0 ) {
2010-08-12 03:35:30 +04:00
memcpy ( urb_out - > transfer_buffer ,
2009-11-16 07:17:50 +03:00
runtime - > dma_area +
2015-01-23 18:10:57 +03:00
line6pcm - > out . pos * bytes_per_frame ,
2009-11-16 07:17:50 +03:00
len * bytes_per_frame ) ;
2010-08-12 03:35:30 +04:00
memcpy ( urb_out - > transfer_buffer +
2009-11-16 07:17:50 +03:00
len * bytes_per_frame , runtime - > dma_area ,
( urb_frames - len ) * bytes_per_frame ) ;
2010-08-12 03:35:30 +04:00
} else
2012-11-11 16:24:43 +04:00
dev_err ( line6pcm - > line6 - > ifcdev , " driver bug: len = %d \n " ,
len ) ;
2009-02-28 09:41:12 +03:00
} else {
2010-08-12 03:35:30 +04:00
memcpy ( urb_out - > transfer_buffer ,
runtime - > dma_area +
2015-01-23 18:10:57 +03:00
line6pcm - > out . pos * bytes_per_frame ,
2010-08-12 03:35:30 +04:00
urb_out - > transfer_buffer_length ) ;
2009-02-28 06:43:04 +03:00
}
2015-01-23 18:10:57 +03:00
line6pcm - > out . pos + = urb_frames ;
if ( line6pcm - > out . pos > = runtime - > buffer_size )
line6pcm - > out . pos - = runtime - > buffer_size ;
2015-01-23 18:58:30 +03:00
change_volume ( urb_out , line6pcm - > volume_playback ,
bytes_per_frame ) ;
2010-08-12 03:35:30 +04:00
} else {
memset ( urb_out - > transfer_buffer , 0 ,
urb_out - > transfer_buffer_length ) ;
}
2009-02-28 06:43:04 +03:00
2015-01-27 14:50:44 +03:00
spin_lock_nested ( & line6pcm - > in . lock , SINGLE_DEPTH_NESTING ) ;
if ( line6pcm - > prev_fbuf ) {
2015-01-27 17:24:09 +03:00
if ( test_bit ( LINE6_STREAM_IMPULSE , & line6pcm - > out . running ) ) {
2010-08-12 03:35:30 +04:00
create_impulse_test_signal ( line6pcm , urb_out ,
bytes_per_frame ) ;
2015-01-27 17:24:09 +03:00
if ( test_bit ( LINE6_STREAM_PCM , & line6pcm - > in . running ) ) {
2010-08-23 03:08:25 +04:00
line6_capture_copy ( line6pcm ,
urb_out - > transfer_buffer ,
urb_out - >
transfer_buffer_length ) ;
line6_capture_check_period ( line6pcm ,
2013-10-23 03:00:22 +04:00
urb_out - > transfer_buffer_length ) ;
2010-08-12 03:35:30 +04:00
}
} else {
2015-01-27 17:24:09 +03:00
if ( ! ( line6pcm - > line6 - > properties - > capabilities & LINE6_CAP_HWMON )
& & line6pcm - > out . running & & line6pcm - > in . running )
2010-08-12 03:35:30 +04:00
add_monitor_signal ( urb_out , line6pcm - > prev_fbuf ,
line6pcm - > volume_monitor ,
bytes_per_frame ) ;
}
2015-01-27 18:17:26 +03:00
line6pcm - > prev_fbuf = NULL ;
line6pcm - > prev_fsize = 0 ;
2010-08-12 03:35:30 +04:00
}
2015-01-27 14:50:44 +03:00
spin_unlock ( & line6pcm - > in . lock ) ;
2009-02-28 06:43:04 +03:00
2010-08-23 03:08:25 +04:00
ret = usb_submit_urb ( urb_out , GFP_ATOMIC ) ;
if ( ret = = 0 )
2015-01-23 18:10:57 +03:00
set_bit ( index , & line6pcm - > out . active_urbs ) ;
2009-02-28 06:43:04 +03:00
else
2010-08-12 03:35:30 +04:00
dev_err ( line6pcm - > line6 - > ifcdev ,
2010-08-23 03:08:25 +04:00
" URB out #%d submission failed (%d) \n " , index , ret ) ;
2009-02-28 06:43:04 +03:00
return 0 ;
}
/*
Submit all currently available playback URBs .
2015-01-27 17:24:09 +03:00
must be called in line6pcm - > out . lock context
*/
2010-08-12 03:35:30 +04:00
int line6_submit_audio_out_all_urbs ( struct snd_line6_pcm * line6pcm )
2009-02-28 06:43:04 +03:00
{
2015-01-27 14:50:44 +03:00
int ret = 0 , i ;
2009-02-28 06:43:04 +03:00
2016-09-18 21:59:21 +03:00
for ( i = 0 ; i < line6pcm - > line6 - > iso_buffers ; + + i ) {
2010-08-12 03:35:30 +04:00
ret = submit_audio_out_urb ( line6pcm ) ;
2009-02-28 09:41:12 +03:00
if ( ret < 0 )
2015-01-27 14:50:44 +03:00
break ;
2009-02-28 09:41:12 +03:00
}
2009-02-28 06:43:04 +03:00
2015-01-27 14:50:44 +03:00
return ret ;
2009-02-28 06:43:04 +03:00
}
/*
Callback for completed playback URB .
*/
2009-02-28 07:28:04 +03:00
static void audio_out_callback ( struct urb * urb )
2009-02-28 06:43:04 +03:00
{
int i , index , length = 0 , shutdown = 0 ;
unsigned long flags ;
2010-08-23 03:08:25 +04:00
struct snd_line6_pcm * line6pcm = ( struct snd_line6_pcm * ) urb - > context ;
2009-11-16 07:17:50 +03:00
struct snd_pcm_substream * substream =
2010-08-12 03:35:30 +04:00
get_substream ( line6pcm , SNDRV_PCM_STREAM_PLAYBACK ) ;
2016-09-18 21:59:24 +03:00
const int bytes_per_frame =
line6pcm - > properties - > bytes_per_channel *
line6pcm - > properties - > playback_hw . channels_max ;
2010-08-12 03:35:30 +04:00
# if USE_CLEAR_BUFFER_WORKAROUND
memset ( urb - > transfer_buffer , 0 , urb - > transfer_buffer_length ) ;
# endif
2015-01-23 18:10:57 +03:00
line6pcm - > out . last_frame = urb - > start_frame ;
2009-02-28 06:43:04 +03:00
/* find index of URB */
2016-09-18 21:59:21 +03:00
for ( index = 0 ; index < line6pcm - > line6 - > iso_buffers ; index + + )
2015-01-23 18:10:57 +03:00
if ( urb = = line6pcm - > out . urbs [ index ] )
2009-02-28 06:43:04 +03:00
break ;
2016-09-18 21:59:21 +03:00
if ( index > = line6pcm - > line6 - > iso_buffers )
2009-11-16 07:17:50 +03:00
return ; /* URB has been unlinked asynchronously */
2009-02-28 06:43:04 +03:00
2015-01-23 17:08:40 +03:00
for ( i = 0 ; i < LINE6_ISO_PACKETS ; i + + )
2009-02-28 06:43:04 +03:00
length + = urb - > iso_frame_desc [ i ] . length ;
2015-01-23 18:10:57 +03:00
spin_lock_irqsave ( & line6pcm - > out . lock , flags ) ;
2009-02-28 06:43:04 +03:00
2015-01-27 17:24:09 +03:00
if ( test_bit ( LINE6_STREAM_PCM , & line6pcm - > out . running ) ) {
2010-08-12 03:35:30 +04:00
struct snd_pcm_runtime * runtime = substream - > runtime ;
2014-04-24 11:31:48 +04:00
2015-01-23 18:10:57 +03:00
line6pcm - > out . pos_done + =
2016-09-18 21:59:24 +03:00
length / bytes_per_frame ;
2010-08-12 03:35:30 +04:00
2015-01-23 18:10:57 +03:00
if ( line6pcm - > out . pos_done > = runtime - > buffer_size )
line6pcm - > out . pos_done - = runtime - > buffer_size ;
2010-08-12 03:35:30 +04:00
}
2009-02-28 06:43:04 +03:00
2015-01-23 18:10:57 +03:00
clear_bit ( index , & line6pcm - > out . active_urbs ) ;
2009-02-28 06:43:04 +03:00
2015-01-23 17:08:40 +03:00
for ( i = 0 ; i < LINE6_ISO_PACKETS ; i + + )
2010-08-23 03:08:25 +04:00
if ( urb - > iso_frame_desc [ i ] . status = = - EXDEV ) {
2009-02-28 06:43:04 +03:00
shutdown = 1 ;
break ;
}
2015-01-23 18:10:57 +03:00
if ( test_and_clear_bit ( index , & line6pcm - > out . unlink_urbs ) )
2009-02-28 06:43:04 +03:00
shutdown = 1 ;
2009-02-28 09:41:12 +03:00
if ( ! shutdown ) {
2010-08-12 03:35:30 +04:00
submit_audio_out_urb ( line6pcm ) ;
2009-02-28 06:43:04 +03:00
2015-01-27 17:24:09 +03:00
if ( test_bit ( LINE6_STREAM_PCM , & line6pcm - > out . running ) ) {
2015-01-23 18:10:57 +03:00
line6pcm - > out . bytes + = length ;
if ( line6pcm - > out . bytes > = line6pcm - > out . period ) {
line6pcm - > out . bytes % = line6pcm - > out . period ;
2015-01-27 14:50:44 +03:00
spin_unlock ( & line6pcm - > out . lock ) ;
2010-08-12 03:35:30 +04:00
snd_pcm_period_elapsed ( substream ) ;
2015-01-27 14:50:44 +03:00
spin_lock ( & line6pcm - > out . lock ) ;
2010-08-12 03:35:30 +04:00
}
2009-02-28 06:43:04 +03:00
}
}
2015-01-27 14:50:44 +03:00
spin_unlock_irqrestore ( & line6pcm - > out . lock , flags ) ;
2009-02-28 06:43:04 +03:00
}
/* open playback callback */
static int snd_line6_playback_open ( struct snd_pcm_substream * substream )
{
int err ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct snd_line6_pcm * line6pcm = snd_pcm_substream_chip ( substream ) ;
2009-02-28 09:41:12 +03:00
err = snd_pcm_hw_constraint_ratdens ( runtime , 0 , SNDRV_PCM_HW_PARAM_RATE ,
2015-01-28 17:08:59 +03:00
& line6pcm - > properties - > rates ) ;
2009-02-28 09:41:12 +03:00
if ( err < 0 )
2009-02-28 06:43:04 +03:00
return err ;
2015-01-28 17:08:59 +03:00
runtime - > hw = line6pcm - > properties - > playback_hw ;
2009-02-28 06:43:04 +03:00
return 0 ;
}
/* close playback callback */
static int snd_line6_playback_close ( struct snd_pcm_substream * substream )
{
return 0 ;
}
/* playback operators */
2017-09-27 09:19:27 +03:00
const struct snd_pcm_ops snd_line6_playback_ops = {
2010-08-23 03:08:25 +04:00
. open = snd_line6_playback_open ,
. close = snd_line6_playback_close ,
2015-01-27 17:24:09 +03:00
. hw_params = snd_line6_hw_params ,
. hw_free = snd_line6_hw_free ,
2010-08-23 03:08:25 +04:00
. prepare = snd_line6_prepare ,
. trigger = snd_line6_trigger ,
2015-01-27 17:41:27 +03:00
. pointer = snd_line6_pointer ,
2009-02-28 06:43:04 +03:00
} ;
2010-08-12 03:35:30 +04:00
int line6_create_audio_out_urbs ( struct snd_line6_pcm * line6pcm )
2009-02-28 06:43:04 +03:00
{
2015-01-12 23:42:55 +03:00
struct usb_line6 * line6 = line6pcm - > line6 ;
2009-02-28 06:43:04 +03:00
int i ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(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 Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- 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;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- 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;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- 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;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- 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;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- 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;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- 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;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
line6pcm - > out . urbs = kcalloc ( line6 - > iso_buffers , sizeof ( struct urb * ) ,
GFP_KERNEL ) ;
2016-09-18 21:59:21 +03:00
if ( line6pcm - > out . urbs = = NULL )
return - ENOMEM ;
2009-02-28 06:43:04 +03:00
/* create audio URBs and fill in constant values: */
2016-09-18 21:59:21 +03:00
for ( i = 0 ; i < line6 - > iso_buffers ; + + i ) {
2009-02-28 06:43:04 +03:00
struct urb * urb ;
/* URB for audio out: */
2015-01-23 18:10:57 +03:00
urb = line6pcm - > out . urbs [ i ] =
2009-11-16 07:17:50 +03:00
usb_alloc_urb ( LINE6_ISO_PACKETS , GFP_KERNEL ) ;
2009-02-28 06:43:04 +03:00
2015-01-19 17:05:10 +03:00
if ( urb = = NULL )
2009-02-28 06:43:04 +03:00
return - ENOMEM ;
2015-01-12 23:42:55 +03:00
urb - > dev = line6 - > usbdev ;
2009-11-16 07:17:50 +03:00
urb - > pipe =
2015-01-12 23:42:55 +03:00
usb_sndisocpipe ( line6 - > usbdev ,
line6 - > properties - > ep_audio_w &
2010-08-23 03:08:25 +04:00
USB_ENDPOINT_NUMBER_MASK ) ;
2009-02-28 06:43:04 +03:00
urb - > transfer_flags = URB_ISO_ASAP ;
urb - > start_frame = - 1 ;
urb - > number_of_packets = LINE6_ISO_PACKETS ;
urb - > interval = LINE6_ISO_INTERVAL ;
urb - > error_count = 0 ;
urb - > complete = audio_out_callback ;
2020-07-10 16:33:51 +03:00
if ( usb_urb_ep_type_check ( urb ) )
return - EINVAL ;
2009-02-28 06:43:04 +03:00
}
return 0 ;
}