patch-1.3.34 linux/drivers/sound/midi_synth.c

Next file: linux/drivers/sound/midi_synth.h
Previous file: linux/drivers/sound/maui.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.33/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
@@ -36,11 +36,15 @@
 
 #define _MIDI_SYNTH_C_
 
-DEFINE_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
+static struct wait_queue *sysex_sleeper = NULL;
+static volatile struct snd_wait sysex_sleep_flag =
+{0};
 
 #include "midi_synth.h"
 
 static int      midi2synth[MAX_MIDI_DEV];
+static int      sysex_state[MAX_MIDI_DEV] =
+{0};
 static unsigned char prev_out_status[MAX_MIDI_DEV];
 
 #define STORE(cmd) \
@@ -95,6 +99,7 @@
 
     default:
       /* printk ("MPU: Unknown midi channel message %02x\n", msg[0]); */
+      ;
     }
 }
 
@@ -242,6 +247,24 @@
 }
 
 static void
+leave_sysex (int dev)
+{
+  int             orig_dev = synth_devs[dev]->midi_dev;
+  int             timeout = 0;
+
+  if (!sysex_state[dev])
+    return;
+
+  sysex_state[dev] = 0;
+
+  while (!midi_devs[orig_dev]->putc (orig_dev, 0xf7) &&
+	 timeout < 1000)
+    timeout++;
+
+  sysex_state[dev] = 0;
+}
+
+static void
 midi_synth_output (int dev)
 {
   /*
@@ -251,7 +274,7 @@
 
 int
 midi_synth_ioctl (int dev,
-		  unsigned int cmd, unsigned int arg)
+		  unsigned int cmd, ioctl_arg arg)
 {
   /*
    * int orig_dev = synth_devs[dev]->midi_dev;
@@ -261,8 +284,7 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      IOCTL_TO_USER ((char *) arg, 0, synth_devs[dev]->info,
-		     sizeof (struct synth_info));
+      memcpy_tofs (&(((char *) arg)[0]), (synth_devs[dev]->info), (sizeof (struct synth_info)));
 
       return 0;
       break;
@@ -272,7 +294,7 @@
       break;
 
     default:
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -291,6 +313,8 @@
   if (velocity > 127)
     velocity = 127;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -352,6 +376,8 @@
   if (channel < 0 || channel > 15)
     return 0;
 
+  leave_sysex (dev);
+
   if (!prefix_cmd (orig_dev, 0xc0 | (channel & 0x0f)))
     return 0;
   midi_outc (orig_dev, 0xc0 | (channel & 0x0f));	/*
@@ -377,6 +403,8 @@
   if (velocity > 127)
     velocity = 127;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -405,6 +433,8 @@
 void
 midi_synth_reset (int dev)
 {
+
+  leave_sysex (dev);
 }
 
 int
@@ -416,9 +446,10 @@
   struct midi_input_info *inc;
 
   if (orig_dev < 0 || orig_dev > num_midis)
-    return RET_ERROR (ENXIO);
+    return -ENXIO;
 
   midi2synth[orig_dev] = dev;
+  sysex_state[dev] = 0;
   prev_out_status[orig_dev] = 0;
 
   if ((err = midi_devs[orig_dev]->open (orig_dev, mode,
@@ -427,13 +458,14 @@
 
   inc = &midi_devs[orig_dev]->in_info;
 
-  DISABLE_INTR (flags);
+  save_flags (flags);
+  cli ();
   inc->m_busy = 0;
   inc->m_state = MST_INIT;
   inc->m_ptr = 0;
   inc->m_left = 0;
   inc->m_prev_status = 0x00;
-  RESTORE_INTR (flags);
+  restore_flags (flags);
 
   return 1;
 }
@@ -443,8 +475,10 @@
 {
   int             orig_dev = synth_devs[dev]->midi_dev;
 
+  leave_sysex (dev);
+
   /*
-     * Shut up the synths by sending just single active sensing message.
+   * Shut up the synths by sending just single active sensing message.
    */
   midi_devs[orig_dev]->putc (orig_dev, 0xfe);
 
@@ -457,7 +491,7 @@
 }
 
 int
-midi_synth_load_patch (int dev, int format, snd_rw_buf * addr,
+midi_synth_load_patch (int dev, int format, const snd_rw_buf * addr,
 		       int offs, int count, int pmgr_flag)
 {
   int             orig_dev = synth_devs[dev]->midi_dev;
@@ -468,19 +502,21 @@
   int             first_byte = 1;
   int             hdr_size = (unsigned long) &sysex.data[0] - (unsigned long) &sysex;
 
+  leave_sysex (dev);
+
   if (!prefix_cmd (orig_dev, 0xf0))
     return 0;
 
   if (format != SYSEX_PATCH)
     {
       printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   if (count < hdr_size)
     {
       printk ("MIDI Error: Patch header too short\n");
-      return RET_ERROR (EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -490,7 +526,7 @@
    * been transferred already.
    */
 
-  COPY_FROM_USER (&((char *) &sysex)[offs], addr, offs, hdr_size - offs);
+  memcpy_fromfs ((&((char *) &sysex)[offs]), &((addr)[offs]), (hdr_size - offs));
 
   if (count < sysex.len)
     {
@@ -502,13 +538,16 @@
   left = sysex.len;
   src_offs = 0;
 
-  RESET_WAIT_QUEUE (sysex_sleeper, sysex_sleep_flag);
+  {
+    sysex_sleep_flag.aborting = 0;
+    sysex_sleep_flag.mode = WK_NONE;
+  };
 
-  for (i = 0; i < left && !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag); i++)
+  for (i = 0; i < left && !((current->signal & ~current->blocked)); i++)
     {
       unsigned char   data;
 
-      GET_BYTE_FROM_USER (data, addr, hdr_size + i);
+      data = get_fs_byte (&((addr)[hdr_size + i]));
 
       eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
@@ -520,13 +559,31 @@
 	  if (data != 0xf0)
 	    {
 	      printk ("Error: Sysex start missing\n");
-	      return RET_ERROR (EINVAL);
+	      return -EINVAL;
 	    }
 	}
 
       while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
-	     !PROCESS_ABORTING (sysex_sleeper, sysex_sleep_flag))
-	DO_SLEEP (sysex_sleeper, sysex_sleep_flag, 1);	/* Wait for timeout */
+	     !((current->signal & ~current->blocked)))
+
+	{
+	  unsigned long   tl;
+
+	  if (1)
+	    tl = current->timeout = jiffies + (1);
+	  else
+	    tl = 0xffffffff;
+	  sysex_sleep_flag.mode = WK_SLEEP;
+	  interruptible_sleep_on (&sysex_sleeper);
+	  if (!(sysex_sleep_flag.mode & WK_WAKEUP))
+	    {
+	      if (current->signal & ~current->blocked)
+		sysex_sleep_flag.aborting = 1;
+	      else if (jiffies >= tl)
+		sysex_sleep_flag.mode |= WK_TIMEOUT;
+	    }
+	  sysex_sleep_flag.mode &= ~WK_SLEEP;
+	};			/* Wait for timeout */
 
       if (!first_byte && data & 0x80)
 	return 0;
@@ -554,6 +611,8 @@
   if (channel < 0 || channel > 15)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -584,6 +643,8 @@
   if (channel < 0 || channel > 15)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -603,7 +664,7 @@
 int
 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return RET_ERROR (EINVAL);
+  return -EINVAL;
 }
 
 void
@@ -618,6 +679,8 @@
   if (value < 0 || value > 16383)
     return;
 
+  leave_sysex (dev);
+
   msg = prev_out_status[orig_dev] & 0xf0;
   prev_chn = prev_out_status[orig_dev] & 0x0f;
 
@@ -639,6 +702,62 @@
 void
 midi_synth_setup_voice (int dev, int voice, int channel)
 {
+}
+
+int
+midi_synth_send_sysex (int dev, unsigned char *bytes, int len)
+{
+  int             orig_dev = synth_devs[dev]->midi_dev;
+  int             i;
+
+  for (i = 0; i < len; i++)
+    {
+      switch (bytes[i])
+	{
+	case 0xf0:		/* Start sysex */
+	  if (!prefix_cmd (orig_dev, 0xf0))
+	    return 0;
+	  sysex_state[dev] = 1;
+	  break;
+
+	case 0xf7:		/* End sysex */
+	  if (!sysex_state[dev])	/* Orphan sysex end */
+	    return 0;
+	  sysex_state[dev] = 0;
+	  break;
+
+	default:
+	  if (!sysex_state[dev])
+	    return 0;
+
+	  if (bytes[i] & 0x80)	/* Error. Another message before sysex end */
+	    {
+	      bytes[i] = 0xf7;	/* Sysex end */
+	      sysex_state[dev] = 0;
+	    }
+	}
+
+      if (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]))
+	{
+/*
+ * Hardware leve buffer is full. Abort the sysex message.
+ */
+
+	  int             timeout = 0;
+
+	  bytes[i] = 0xf7;
+	  sysex_state[dev] = 0;
+
+	  while (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]) &&
+		 timeout < 1000)
+	    timeout++;
+	}
+
+      if (!sysex_state[dev])
+	return 0;
+    }
+
+  return 0;
 }
 
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this