2019-05-27 08:55:05 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* MIDI byte < - > sequencer event coder
*
* Copyright ( C ) 1998 , 99 Takashi Iwai < tiwai @ suse . de > ,
2007-10-15 09:50:19 +02:00
* Jaroslav Kysela < perex @ perex . cz >
2005-04-16 15:20:36 -07:00
*/
# include <linux/slab.h>
# include <linux/errno.h>
# include <linux/string.h>
2011-07-15 12:38:28 -04:00
# include <linux/module.h>
2005-04-16 15:20:36 -07:00
# include <sound/core.h>
# include <sound/seq_kernel.h>
# include <sound/seq_midi_event.h>
# include <sound/asoundef.h>
2007-10-15 09:50:19 +02:00
MODULE_AUTHOR ( " Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz> " ) ;
2005-04-16 15:20:36 -07:00
MODULE_DESCRIPTION ( " MIDI byte <-> sequencer event coder " ) ;
MODULE_LICENSE ( " GPL " ) ;
2007-08-10 09:38:36 +02:00
/* event type, index into status_event[] */
/* from 0 to 6 are normal commands (note off, on, etc.) for 0x9?-0xe? */
# define ST_INVALID 7
2005-04-16 15:20:36 -07:00
# define ST_SPECIAL 8
# define ST_SYSEX ST_SPECIAL
/* from 8 to 15 are events for 0xf0-0xf7 */
/*
* prototypes
*/
2005-11-17 14:04:02 +01:00
static void note_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void one_param_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void pitchbend_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void two_param_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void one_param_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void songpos_event ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
static void note_decode ( struct snd_seq_event * ev , unsigned char * buf ) ;
static void one_param_decode ( struct snd_seq_event * ev , unsigned char * buf ) ;
static void pitchbend_decode ( struct snd_seq_event * ev , unsigned char * buf ) ;
static void two_param_decode ( struct snd_seq_event * ev , unsigned char * buf ) ;
static void songpos_decode ( struct snd_seq_event * ev , unsigned char * buf ) ;
2005-04-16 15:20:36 -07:00
/*
* event list
*/
2005-11-17 14:04:02 +01:00
static struct status_event_list {
2005-04-16 15:20:36 -07:00
int event ;
int qlen ;
2005-11-17 14:04:02 +01:00
void ( * encode ) ( struct snd_midi_event * dev , struct snd_seq_event * ev ) ;
void ( * decode ) ( struct snd_seq_event * ev , unsigned char * buf ) ;
2005-04-16 15:20:36 -07:00
} status_event [ ] = {
2007-08-10 09:38:36 +02:00
/* 0x80 - 0xef */
2007-08-10 09:40:09 +02:00
{ SNDRV_SEQ_EVENT_NOTEOFF , 2 , note_event , note_decode } ,
{ SNDRV_SEQ_EVENT_NOTEON , 2 , note_event , note_decode } ,
{ SNDRV_SEQ_EVENT_KEYPRESS , 2 , note_event , note_decode } ,
{ SNDRV_SEQ_EVENT_CONTROLLER , 2 , two_param_ctrl_event , two_param_decode } ,
{ SNDRV_SEQ_EVENT_PGMCHANGE , 1 , one_param_ctrl_event , one_param_decode } ,
{ SNDRV_SEQ_EVENT_CHANPRESS , 1 , one_param_ctrl_event , one_param_decode } ,
{ SNDRV_SEQ_EVENT_PITCHBEND , 2 , pitchbend_ctrl_event , pitchbend_decode } ,
2007-08-10 09:38:36 +02:00
/* invalid */
2007-08-10 09:40:09 +02:00
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } ,
2005-04-16 15:20:36 -07:00
/* 0xf0 - 0xff */
2007-08-10 09:40:09 +02:00
{ SNDRV_SEQ_EVENT_SYSEX , 1 , NULL , NULL } , /* sysex: 0xf0 */
{ SNDRV_SEQ_EVENT_QFRAME , 1 , one_param_event , one_param_decode } , /* 0xf1 */
{ SNDRV_SEQ_EVENT_SONGPOS , 2 , songpos_event , songpos_decode } , /* 0xf2 */
{ SNDRV_SEQ_EVENT_SONGSEL , 1 , one_param_event , one_param_decode } , /* 0xf3 */
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } , /* 0xf4 */
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } , /* 0xf5 */
{ SNDRV_SEQ_EVENT_TUNE_REQUEST , 0 , NULL , NULL } , /* 0xf6 */
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } , /* 0xf7 */
{ SNDRV_SEQ_EVENT_CLOCK , 0 , NULL , NULL } , /* 0xf8 */
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } , /* 0xf9 */
{ SNDRV_SEQ_EVENT_START , 0 , NULL , NULL } , /* 0xfa */
{ SNDRV_SEQ_EVENT_CONTINUE , 0 , NULL , NULL } , /* 0xfb */
{ SNDRV_SEQ_EVENT_STOP , 0 , NULL , NULL } , /* 0xfc */
{ SNDRV_SEQ_EVENT_NONE , - 1 , NULL , NULL } , /* 0xfd */
{ SNDRV_SEQ_EVENT_SENSING , 0 , NULL , NULL } , /* 0xfe */
{ SNDRV_SEQ_EVENT_RESET , 0 , NULL , NULL } , /* 0xff */
2005-04-16 15:20:36 -07:00
} ;
2005-11-17 14:04:02 +01:00
static int extra_decode_ctrl14 ( struct snd_midi_event * dev , unsigned char * buf , int len ,
struct snd_seq_event * ev ) ;
static int extra_decode_xrpn ( struct snd_midi_event * dev , unsigned char * buf , int count ,
struct snd_seq_event * ev ) ;
2005-04-16 15:20:36 -07:00
2005-11-17 14:04:02 +01:00
static struct extra_event_list {
2005-04-16 15:20:36 -07:00
int event ;
2005-11-17 14:04:02 +01:00
int ( * decode ) ( struct snd_midi_event * dev , unsigned char * buf , int len ,
struct snd_seq_event * ev ) ;
2005-04-16 15:20:36 -07:00
} extra_event [ ] = {
{ SNDRV_SEQ_EVENT_CONTROL14 , extra_decode_ctrl14 } ,
{ SNDRV_SEQ_EVENT_NONREGPARAM , extra_decode_xrpn } ,
{ SNDRV_SEQ_EVENT_REGPARAM , extra_decode_xrpn } ,
} ;
/*
* new / delete record
*/
2005-11-17 14:04:02 +01:00
int snd_midi_event_new ( int bufsize , struct snd_midi_event * * rdev )
2005-04-16 15:20:36 -07:00
{
2005-11-17 14:04:02 +01:00
struct snd_midi_event * dev ;
2005-04-16 15:20:36 -07:00
* rdev = NULL ;
2005-09-09 14:20:49 +02:00
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( dev = = NULL )
return - ENOMEM ;
if ( bufsize > 0 ) {
dev - > buf = kmalloc ( bufsize , GFP_KERNEL ) ;
if ( dev - > buf = = NULL ) {
kfree ( dev ) ;
return - ENOMEM ;
}
}
dev - > bufsize = bufsize ;
dev - > lastcmd = 0xff ;
2007-08-10 09:38:36 +02:00
dev - > type = ST_INVALID ;
2005-04-16 15:20:36 -07:00
spin_lock_init ( & dev - > lock ) ;
* rdev = dev ;
return 0 ;
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_new ) ;
2005-04-16 15:20:36 -07:00
2005-11-17 14:04:02 +01:00
void snd_midi_event_free ( struct snd_midi_event * dev )
2005-04-16 15:20:36 -07:00
{
if ( dev ! = NULL ) {
kfree ( dev - > buf ) ;
kfree ( dev ) ;
}
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_free ) ;
2005-04-16 15:20:36 -07:00
/*
* initialize record
*/
2005-11-17 14:04:02 +01:00
static inline void reset_encode ( struct snd_midi_event * dev )
2005-04-16 15:20:36 -07:00
{
dev - > read = 0 ;
dev - > qlen = 0 ;
2007-08-10 09:38:36 +02:00
dev - > type = ST_INVALID ;
2005-04-16 15:20:36 -07:00
}
2005-11-17 14:04:02 +01:00
void snd_midi_event_reset_encode ( struct snd_midi_event * dev )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
spin_lock_irqsave ( & dev - > lock , flags ) ;
reset_encode ( dev ) ;
spin_unlock_irqrestore ( & dev - > lock , flags ) ;
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_reset_encode ) ;
2005-04-16 15:20:36 -07:00
2005-11-17 14:04:02 +01:00
void snd_midi_event_reset_decode ( struct snd_midi_event * dev )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
spin_lock_irqsave ( & dev - > lock , flags ) ;
dev - > lastcmd = 0xff ;
spin_unlock_irqrestore ( & dev - > lock , flags ) ;
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_reset_decode ) ;
2005-04-16 15:20:36 -07:00
2005-11-17 14:04:02 +01:00
void snd_midi_event_no_status ( struct snd_midi_event * dev , int on )
2005-04-16 15:20:36 -07:00
{
dev - > nostat = on ? 1 : 0 ;
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_no_status ) ;
2005-04-16 15:20:36 -07:00
/*
* read one byte and encode to sequencer event :
2018-08-01 14:38:18 +02:00
* return true if MIDI bytes are encoded to an event
* false data is not finished
2005-04-16 15:20:36 -07:00
*/
2018-08-01 14:38:18 +02:00
bool snd_midi_event_encode_byte ( struct snd_midi_event * dev , unsigned char c ,
struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
2018-08-01 14:38:18 +02:00
bool rc = false ;
2005-04-16 15:20:36 -07:00
unsigned long flags ;
if ( c > = MIDI_CMD_COMMON_CLOCK ) {
/* real-time event */
ev - > type = status_event [ ST_SPECIAL + c - 0xf0 ] . event ;
ev - > flags & = ~ SNDRV_SEQ_EVENT_LENGTH_MASK ;
ev - > flags | = SNDRV_SEQ_EVENT_LENGTH_FIXED ;
2007-08-10 09:41:07 +02:00
return ev - > type ! = SNDRV_SEQ_EVENT_NONE ;
2005-04-16 15:20:36 -07:00
}
spin_lock_irqsave ( & dev - > lock , flags ) ;
2007-08-10 09:40:09 +02:00
if ( ( c & 0x80 ) & &
( c ! = MIDI_CMD_COMMON_SYSEX_END | | dev - > type ! = ST_SYSEX ) ) {
2005-04-16 15:20:36 -07:00
/* new command */
2007-08-10 09:40:09 +02:00
dev - > buf [ 0 ] = c ;
if ( ( c & 0xf0 ) = = 0xf0 ) /* system messages */
dev - > type = ( c & 0x0f ) + ST_SPECIAL ;
else
dev - > type = ( c > > 4 ) & 0x07 ;
2005-04-16 15:20:36 -07:00
dev - > read = 1 ;
2007-08-10 09:40:09 +02:00
dev - > qlen = status_event [ dev - > type ] . qlen ;
} else {
if ( dev - > qlen > 0 ) {
/* rest of command */
2005-04-16 15:20:36 -07:00
dev - > buf [ dev - > read + + ] = c ;
2007-08-10 09:40:09 +02:00
if ( dev - > type ! = ST_SYSEX )
dev - > qlen - - ;
} else {
/* running status */
dev - > buf [ 1 ] = c ;
2005-04-16 15:20:36 -07:00
dev - > qlen = status_event [ dev - > type ] . qlen - 1 ;
2007-08-10 09:40:09 +02:00
dev - > read = 2 ;
2005-04-16 15:20:36 -07:00
}
}
if ( dev - > qlen = = 0 ) {
ev - > type = status_event [ dev - > type ] . event ;
ev - > flags & = ~ SNDRV_SEQ_EVENT_LENGTH_MASK ;
ev - > flags | = SNDRV_SEQ_EVENT_LENGTH_FIXED ;
if ( status_event [ dev - > type ] . encode ) /* set data values */
status_event [ dev - > type ] . encode ( dev , ev ) ;
2007-08-10 09:39:14 +02:00
if ( dev - > type > = ST_SPECIAL )
dev - > type = ST_INVALID ;
2018-08-01 14:38:18 +02:00
rc = true ;
2005-04-16 15:20:36 -07:00
} else if ( dev - > type = = ST_SYSEX ) {
if ( c = = MIDI_CMD_COMMON_SYSEX_END | |
dev - > read > = dev - > bufsize ) {
ev - > flags & = ~ SNDRV_SEQ_EVENT_LENGTH_MASK ;
ev - > flags | = SNDRV_SEQ_EVENT_LENGTH_VARIABLE ;
ev - > type = SNDRV_SEQ_EVENT_SYSEX ;
ev - > data . ext . len = dev - > read ;
ev - > data . ext . ptr = dev - > buf ;
if ( c ! = MIDI_CMD_COMMON_SYSEX_END )
dev - > read = 0 ; /* continue to parse */
else
reset_encode ( dev ) ; /* all parsed */
2018-08-01 14:38:18 +02:00
rc = true ;
2005-04-16 15:20:36 -07:00
}
}
spin_unlock_irqrestore ( & dev - > lock , flags ) ;
return rc ;
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_encode_byte ) ;
2005-04-16 15:20:36 -07:00
/* encode note event */
2005-11-17 14:04:02 +01:00
static void note_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . note . channel = dev - > buf [ 0 ] & 0x0f ;
ev - > data . note . note = dev - > buf [ 1 ] ;
ev - > data . note . velocity = dev - > buf [ 2 ] ;
}
/* encode one parameter controls */
2005-11-17 14:04:02 +01:00
static void one_param_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . control . channel = dev - > buf [ 0 ] & 0x0f ;
ev - > data . control . value = dev - > buf [ 1 ] ;
}
/* encode pitch wheel change */
2005-11-17 14:04:02 +01:00
static void pitchbend_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . control . channel = dev - > buf [ 0 ] & 0x0f ;
ev - > data . control . value = ( int ) dev - > buf [ 2 ] * 128 + ( int ) dev - > buf [ 1 ] - 8192 ;
}
/* encode midi control change */
2005-11-17 14:04:02 +01:00
static void two_param_ctrl_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . control . channel = dev - > buf [ 0 ] & 0x0f ;
ev - > data . control . param = dev - > buf [ 1 ] ;
ev - > data . control . value = dev - > buf [ 2 ] ;
}
/* encode one parameter value*/
2005-11-17 14:04:02 +01:00
static void one_param_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . control . value = dev - > buf [ 1 ] ;
}
/* encode song position */
2005-11-17 14:04:02 +01:00
static void songpos_event ( struct snd_midi_event * dev , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
ev - > data . control . value = ( int ) dev - > buf [ 2 ] * 128 + ( int ) dev - > buf [ 1 ] ;
}
/*
* decode from a sequencer event to midi bytes
* return the size of decoded midi events
*/
2005-11-17 14:04:02 +01:00
long snd_midi_event_decode ( struct snd_midi_event * dev , unsigned char * buf , long count ,
struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
unsigned int cmd , type ;
if ( ev - > type = = SNDRV_SEQ_EVENT_NONE )
return - ENOENT ;
for ( type = 0 ; type < ARRAY_SIZE ( status_event ) ; type + + ) {
if ( ev - > type = = status_event [ type ] . event )
goto __found ;
}
for ( type = 0 ; type < ARRAY_SIZE ( extra_event ) ; type + + ) {
if ( ev - > type = = extra_event [ type ] . event )
return extra_event [ type ] . decode ( dev , buf , count , ev ) ;
}
return - ENOENT ;
__found :
if ( type > = ST_SPECIAL )
cmd = 0xf0 + ( type - ST_SPECIAL ) ;
else
/* data.note.channel and data.control.channel is identical */
cmd = 0x80 | ( type < < 4 ) | ( ev - > data . note . channel & 0x0f ) ;
if ( cmd = = MIDI_CMD_COMMON_SYSEX ) {
snd_midi_event_reset_decode ( dev ) ;
return snd_seq_expand_var_event ( ev , count , buf , 1 , 0 ) ;
} else {
int qlen ;
unsigned char xbuf [ 4 ] ;
unsigned long flags ;
spin_lock_irqsave ( & dev - > lock , flags ) ;
if ( ( cmd & 0xf0 ) = = 0xf0 | | dev - > lastcmd ! = cmd | | dev - > nostat ) {
dev - > lastcmd = cmd ;
spin_unlock_irqrestore ( & dev - > lock , flags ) ;
xbuf [ 0 ] = cmd ;
if ( status_event [ type ] . decode )
status_event [ type ] . decode ( ev , xbuf + 1 ) ;
qlen = status_event [ type ] . qlen + 1 ;
} else {
spin_unlock_irqrestore ( & dev - > lock , flags ) ;
if ( status_event [ type ] . decode )
status_event [ type ] . decode ( ev , xbuf + 0 ) ;
qlen = status_event [ type ] . qlen ;
}
if ( count < qlen )
return - ENOMEM ;
memcpy ( buf , xbuf , qlen ) ;
return qlen ;
}
}
2017-06-16 16:15:24 +02:00
EXPORT_SYMBOL ( snd_midi_event_decode ) ;
2005-04-16 15:20:36 -07:00
/* decode note event */
2005-11-17 14:04:02 +01:00
static void note_decode ( struct snd_seq_event * ev , unsigned char * buf )
2005-04-16 15:20:36 -07:00
{
buf [ 0 ] = ev - > data . note . note & 0x7f ;
buf [ 1 ] = ev - > data . note . velocity & 0x7f ;
}
/* decode one parameter controls */
2005-11-17 14:04:02 +01:00
static void one_param_decode ( struct snd_seq_event * ev , unsigned char * buf )
2005-04-16 15:20:36 -07:00
{
buf [ 0 ] = ev - > data . control . value & 0x7f ;
}
/* decode pitch wheel change */
2005-11-17 14:04:02 +01:00
static void pitchbend_decode ( struct snd_seq_event * ev , unsigned char * buf )
2005-04-16 15:20:36 -07:00
{
int value = ev - > data . control . value + 8192 ;
buf [ 0 ] = value & 0x7f ;
buf [ 1 ] = ( value > > 7 ) & 0x7f ;
}
/* decode midi control change */
2005-11-17 14:04:02 +01:00
static void two_param_decode ( struct snd_seq_event * ev , unsigned char * buf )
2005-04-16 15:20:36 -07:00
{
buf [ 0 ] = ev - > data . control . param & 0x7f ;
buf [ 1 ] = ev - > data . control . value & 0x7f ;
}
/* decode song position */
2005-11-17 14:04:02 +01:00
static void songpos_decode ( struct snd_seq_event * ev , unsigned char * buf )
2005-04-16 15:20:36 -07:00
{
buf [ 0 ] = ev - > data . control . value & 0x7f ;
buf [ 1 ] = ( ev - > data . control . value > > 7 ) & 0x7f ;
}
/* decode 14bit control */
2005-11-17 14:04:02 +01:00
static int extra_decode_ctrl14 ( struct snd_midi_event * dev , unsigned char * buf ,
int count , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
unsigned char cmd ;
int idx = 0 ;
cmd = MIDI_CMD_CONTROL | ( ev - > data . control . channel & 0x0f ) ;
if ( ev - > data . control . param < 0x20 ) {
if ( count < 4 )
return - ENOMEM ;
if ( dev - > nostat & & count < 6 )
return - ENOMEM ;
if ( cmd ! = dev - > lastcmd | | dev - > nostat ) {
if ( count < 5 )
return - ENOMEM ;
buf [ idx + + ] = dev - > lastcmd = cmd ;
}
buf [ idx + + ] = ev - > data . control . param ;
buf [ idx + + ] = ( ev - > data . control . value > > 7 ) & 0x7f ;
if ( dev - > nostat )
buf [ idx + + ] = cmd ;
buf [ idx + + ] = ev - > data . control . param + 0x20 ;
buf [ idx + + ] = ev - > data . control . value & 0x7f ;
} else {
if ( count < 2 )
return - ENOMEM ;
if ( cmd ! = dev - > lastcmd | | dev - > nostat ) {
if ( count < 3 )
return - ENOMEM ;
buf [ idx + + ] = dev - > lastcmd = cmd ;
}
buf [ idx + + ] = ev - > data . control . param & 0x7f ;
buf [ idx + + ] = ev - > data . control . value & 0x7f ;
}
return idx ;
}
/* decode reg/nonreg param */
2005-11-17 14:04:02 +01:00
static int extra_decode_xrpn ( struct snd_midi_event * dev , unsigned char * buf ,
int count , struct snd_seq_event * ev )
2005-04-16 15:20:36 -07:00
{
unsigned char cmd ;
2020-01-05 15:47:21 +01:00
const char * cbytes ;
static const char cbytes_nrpn [ 4 ] = { MIDI_CTL_NONREG_PARM_NUM_MSB ,
2005-04-16 15:20:36 -07:00
MIDI_CTL_NONREG_PARM_NUM_LSB ,
MIDI_CTL_MSB_DATA_ENTRY ,
MIDI_CTL_LSB_DATA_ENTRY } ;
2020-01-05 15:47:21 +01:00
static const char cbytes_rpn [ 4 ] = { MIDI_CTL_REGIST_PARM_NUM_MSB ,
2005-04-16 15:20:36 -07:00
MIDI_CTL_REGIST_PARM_NUM_LSB ,
MIDI_CTL_MSB_DATA_ENTRY ,
MIDI_CTL_LSB_DATA_ENTRY } ;
unsigned char bytes [ 4 ] ;
int idx = 0 , i ;
if ( count < 8 )
return - ENOMEM ;
if ( dev - > nostat & & count < 12 )
return - ENOMEM ;
cmd = MIDI_CMD_CONTROL | ( ev - > data . control . channel & 0x0f ) ;
2009-06-22 10:01:59 +02:00
bytes [ 0 ] = ( ev - > data . control . param & 0x3f80 ) > > 7 ;
bytes [ 1 ] = ev - > data . control . param & 0x007f ;
bytes [ 2 ] = ( ev - > data . control . value & 0x3f80 ) > > 7 ;
bytes [ 3 ] = ev - > data . control . value & 0x007f ;
2005-04-16 15:20:36 -07:00
if ( cmd ! = dev - > lastcmd & & ! dev - > nostat ) {
if ( count < 9 )
return - ENOMEM ;
buf [ idx + + ] = dev - > lastcmd = cmd ;
}
cbytes = ev - > type = = SNDRV_SEQ_EVENT_NONREGPARAM ? cbytes_nrpn : cbytes_rpn ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( dev - > nostat )
buf [ idx + + ] = dev - > lastcmd = cmd ;
buf [ idx + + ] = cbytes [ i ] ;
buf [ idx + + ] = bytes [ i ] ;
}
return idx ;
}