@@ -126,8 +126,10 @@ struct snd_usb_midi {
126126 struct snd_usb_midi_in_endpoint * in ;
127127 } endpoints [MIDI_MAX_ENDPOINTS ];
128128 unsigned long input_triggered ;
129- unsigned int opened ;
129+ bool autopm_reference ;
130+ unsigned int opened [2 ];
130131 unsigned char disconnected ;
132+ unsigned char input_running ;
131133
132134 struct snd_kcontrol * roland_load_ctl ;
133135};
@@ -149,7 +151,6 @@ struct snd_usb_midi_out_endpoint {
149151 struct snd_usb_midi_out_endpoint * ep ;
150152 struct snd_rawmidi_substream * substream ;
151153 int active ;
152- bool autopm_reference ;
153154 uint8_t cable ; /* cable number << 4 */
154155 uint8_t state ;
155156#define STATE_UNKNOWN 0
@@ -1034,44 +1035,65 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi)
10341035 snd_usbmidi_input_start (& umidi -> list );
10351036}
10361037
1037- static void substream_open (struct snd_rawmidi_substream * substream , int open )
1038+ static int substream_open (struct snd_rawmidi_substream * substream , int dir ,
1039+ int open )
10381040{
10391041 struct snd_usb_midi * umidi = substream -> rmidi -> private_data ;
10401042 struct snd_kcontrol * ctl ;
1043+ int err ;
10411044
10421045 down_read (& umidi -> disc_rwsem );
10431046 if (umidi -> disconnected ) {
10441047 up_read (& umidi -> disc_rwsem );
1045- return ;
1048+ return open ? - ENODEV : 0 ;
10461049 }
10471050
10481051 mutex_lock (& umidi -> mutex );
10491052 if (open ) {
1050- if (umidi -> opened ++ == 0 && umidi -> roland_load_ctl ) {
1051- ctl = umidi -> roland_load_ctl ;
1052- ctl -> vd [0 ].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
1053- snd_ctl_notify (umidi -> card ,
1053+ if (!umidi -> opened [0 ] && !umidi -> opened [1 ]) {
1054+ err = usb_autopm_get_interface (umidi -> iface );
1055+ umidi -> autopm_reference = err >= 0 ;
1056+ if (err < 0 && err != - EACCES ) {
1057+ mutex_unlock (& umidi -> mutex );
1058+ up_read (& umidi -> disc_rwsem );
1059+ return - EIO ;
1060+ }
1061+ if (umidi -> roland_load_ctl ) {
1062+ ctl = umidi -> roland_load_ctl ;
1063+ ctl -> vd [0 ].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
1064+ snd_ctl_notify (umidi -> card ,
10541065 SNDRV_CTL_EVENT_MASK_INFO , & ctl -> id );
1055- update_roland_altsetting (umidi );
1066+ update_roland_altsetting (umidi );
1067+ }
10561068 }
1069+ umidi -> opened [dir ]++ ;
1070+ if (umidi -> opened [1 ])
1071+ snd_usbmidi_input_start (& umidi -> list );
10571072 } else {
1058- if (-- umidi -> opened == 0 && umidi -> roland_load_ctl ) {
1059- ctl = umidi -> roland_load_ctl ;
1060- ctl -> vd [0 ].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
1061- snd_ctl_notify (umidi -> card ,
1073+ umidi -> opened [dir ]-- ;
1074+ if (!umidi -> opened [1 ])
1075+ snd_usbmidi_input_stop (& umidi -> list );
1076+ if (!umidi -> opened [0 ] && !umidi -> opened [1 ]) {
1077+ if (umidi -> roland_load_ctl ) {
1078+ ctl = umidi -> roland_load_ctl ;
1079+ ctl -> vd [0 ].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE ;
1080+ snd_ctl_notify (umidi -> card ,
10621081 SNDRV_CTL_EVENT_MASK_INFO , & ctl -> id );
1082+ }
1083+ if (umidi -> autopm_reference )
1084+ usb_autopm_put_interface (umidi -> iface );
10631085 }
10641086 }
10651087 mutex_unlock (& umidi -> mutex );
10661088 up_read (& umidi -> disc_rwsem );
1089+ return 0 ;
10671090}
10681091
10691092static int snd_usbmidi_output_open (struct snd_rawmidi_substream * substream )
10701093{
10711094 struct snd_usb_midi * umidi = substream -> rmidi -> private_data ;
10721095 struct usbmidi_out_port * port = NULL ;
10731096 int i , j ;
1074- int err ;
10751097
10761098 for (i = 0 ; i < MIDI_MAX_ENDPOINTS ; ++ i )
10771099 if (umidi -> endpoints [i ].out )
@@ -1085,33 +1107,14 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
10851107 return - ENXIO ;
10861108 }
10871109
1088- down_read (& umidi -> disc_rwsem );
1089- if (umidi -> disconnected ) {
1090- up_read (& umidi -> disc_rwsem );
1091- return - ENODEV ;
1092- }
1093- err = usb_autopm_get_interface (umidi -> iface );
1094- port -> autopm_reference = err >= 0 ;
1095- up_read (& umidi -> disc_rwsem );
1096- if (err < 0 && err != - EACCES )
1097- return - EIO ;
10981110 substream -> runtime -> private_data = port ;
10991111 port -> state = STATE_UNKNOWN ;
1100- substream_open (substream , 1 );
1101- return 0 ;
1112+ return substream_open (substream , 0 , 1 );
11021113}
11031114
11041115static int snd_usbmidi_output_close (struct snd_rawmidi_substream * substream )
11051116{
1106- struct snd_usb_midi * umidi = substream -> rmidi -> private_data ;
1107- struct usbmidi_out_port * port = substream -> runtime -> private_data ;
1108-
1109- substream_open (substream , 0 );
1110- down_read (& umidi -> disc_rwsem );
1111- if (!umidi -> disconnected && port -> autopm_reference )
1112- usb_autopm_put_interface (umidi -> iface );
1113- up_read (& umidi -> disc_rwsem );
1114- return 0 ;
1117+ return substream_open (substream , 0 , 0 );
11151118}
11161119
11171120static void snd_usbmidi_output_trigger (struct snd_rawmidi_substream * substream , int up )
@@ -1164,14 +1167,12 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
11641167
11651168static int snd_usbmidi_input_open (struct snd_rawmidi_substream * substream )
11661169{
1167- substream_open (substream , 1 );
1168- return 0 ;
1170+ return substream_open (substream , 1 , 1 );
11691171}
11701172
11711173static int snd_usbmidi_input_close (struct snd_rawmidi_substream * substream )
11721174{
1173- substream_open (substream , 0 );
1174- return 0 ;
1175+ return substream_open (substream , 1 , 0 );
11751176}
11761177
11771178static void snd_usbmidi_input_trigger (struct snd_rawmidi_substream * substream , int up )
@@ -2080,12 +2081,15 @@ void snd_usbmidi_input_stop(struct list_head* p)
20802081 unsigned int i , j ;
20812082
20822083 umidi = list_entry (p , struct snd_usb_midi , list );
2084+ if (!umidi -> input_running )
2085+ return ;
20832086 for (i = 0 ; i < MIDI_MAX_ENDPOINTS ; ++ i ) {
20842087 struct snd_usb_midi_endpoint * ep = & umidi -> endpoints [i ];
20852088 if (ep -> in )
20862089 for (j = 0 ; j < INPUT_URBS ; ++ j )
20872090 usb_kill_urb (ep -> in -> urbs [j ]);
20882091 }
2092+ umidi -> input_running = 0 ;
20892093}
20902094
20912095static void snd_usbmidi_input_start_ep (struct snd_usb_midi_in_endpoint * ep )
@@ -2110,8 +2114,11 @@ void snd_usbmidi_input_start(struct list_head* p)
21102114 int i ;
21112115
21122116 umidi = list_entry (p , struct snd_usb_midi , list );
2117+ if (umidi -> input_running || !umidi -> opened [1 ])
2118+ return ;
21132119 for (i = 0 ; i < MIDI_MAX_ENDPOINTS ; ++ i )
21142120 snd_usbmidi_input_start_ep (umidi -> endpoints [i ].in );
2121+ umidi -> input_running = 1 ;
21152122}
21162123
21172124/*
@@ -2250,9 +2257,6 @@ int snd_usbmidi_create(struct snd_card *card,
22502257 }
22512258
22522259 list_add_tail (& umidi -> list , midi_list );
2253-
2254- for (i = 0 ; i < MIDI_MAX_ENDPOINTS ; ++ i )
2255- snd_usbmidi_input_start_ep (umidi -> endpoints [i ].in );
22562260 return 0 ;
22572261}
22582262
0 commit comments