|
@@ -1055,23 +1055,16 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
|
|
|
EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
|
|
|
|
|
|
/**
|
|
|
- * snd_rawmidi_transmit_peek - copy data from the internal buffer
|
|
|
+ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
|
|
|
* @substream: the rawmidi substream
|
|
|
* @buffer: the buffer pointer
|
|
|
* @count: data size to transfer
|
|
|
*
|
|
|
- * Copies data from the internal output buffer to the given buffer.
|
|
|
- *
|
|
|
- * Call this in the interrupt handler when the midi output is ready,
|
|
|
- * and call snd_rawmidi_transmit_ack() after the transmission is
|
|
|
- * finished.
|
|
|
- *
|
|
|
- * Return: The size of copied data, or a negative error code on failure.
|
|
|
+ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
|
|
|
*/
|
|
|
-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|
|
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|
|
unsigned char *buffer, int count)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
int result, count1;
|
|
|
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
|
|
@@ -1081,7 +1074,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
result = 0;
|
|
|
- spin_lock_irqsave(&runtime->lock, flags);
|
|
|
if (runtime->avail >= runtime->buffer_size) {
|
|
|
/* warning: lowlevel layer MUST trigger down the hardware */
|
|
|
goto __skip;
|
|
@@ -1106,25 +1098,47 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|
|
}
|
|
|
}
|
|
|
__skip:
|
|
|
+ return result;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_rawmidi_transmit_peek - copy data from the internal buffer
|
|
|
+ * @substream: the rawmidi substream
|
|
|
+ * @buffer: the buffer pointer
|
|
|
+ * @count: data size to transfer
|
|
|
+ *
|
|
|
+ * Copies data from the internal output buffer to the given buffer.
|
|
|
+ *
|
|
|
+ * Call this in the interrupt handler when the midi output is ready,
|
|
|
+ * and call snd_rawmidi_transmit_ack() after the transmission is
|
|
|
+ * finished.
|
|
|
+ *
|
|
|
+ * Return: The size of copied data, or a negative error code on failure.
|
|
|
+ */
|
|
|
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
|
|
|
+ unsigned char *buffer, int count)
|
|
|
+{
|
|
|
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
+ int result;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&runtime->lock, flags);
|
|
|
+ result = __snd_rawmidi_transmit_peek(substream, buffer, count);
|
|
|
spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
return result;
|
|
|
}
|
|
|
EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
|
|
|
|
|
|
/**
|
|
|
- * snd_rawmidi_transmit_ack - acknowledge the transmission
|
|
|
+ * __snd_rawmidi_transmit_ack - acknowledge the transmission
|
|
|
* @substream: the rawmidi substream
|
|
|
* @count: the transferred count
|
|
|
*
|
|
|
- * Advances the hardware pointer for the internal output buffer with
|
|
|
- * the given size and updates the condition.
|
|
|
- * Call after the transmission is finished.
|
|
|
- *
|
|
|
- * Return: The advanced size if successful, or a negative error code on failure.
|
|
|
+ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
|
|
|
*/
|
|
|
-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|
|
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
|
|
|
if (runtime->buffer == NULL) {
|
|
@@ -1132,7 +1146,6 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|
|
"snd_rawmidi_transmit_ack: output is not active!!!\n");
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- spin_lock_irqsave(&runtime->lock, flags);
|
|
|
snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
|
|
|
runtime->hw_ptr += count;
|
|
|
runtime->hw_ptr %= runtime->buffer_size;
|
|
@@ -1142,9 +1155,32 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|
|
if (runtime->drain || snd_rawmidi_ready(substream))
|
|
|
wake_up(&runtime->sleep);
|
|
|
}
|
|
|
- spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
return count;
|
|
|
}
|
|
|
+EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
|
|
|
+
|
|
|
+/**
|
|
|
+ * snd_rawmidi_transmit_ack - acknowledge the transmission
|
|
|
+ * @substream: the rawmidi substream
|
|
|
+ * @count: the transferred count
|
|
|
+ *
|
|
|
+ * Advances the hardware pointer for the internal output buffer with
|
|
|
+ * the given size and updates the condition.
|
|
|
+ * Call after the transmission is finished.
|
|
|
+ *
|
|
|
+ * Return: The advanced size if successful, or a negative error code on failure.
|
|
|
+ */
|
|
|
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
|
|
|
+{
|
|
|
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
+ int result;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&runtime->lock, flags);
|
|
|
+ result = __snd_rawmidi_transmit_ack(substream, count);
|
|
|
+ spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
+ return result;
|
|
|
+}
|
|
|
EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
|
|
|
|
|
|
/**
|
|
@@ -1160,12 +1196,22 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
|
|
|
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
|
|
|
unsigned char *buffer, int count)
|
|
|
{
|
|
|
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
|
|
|
+ int result;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&runtime->lock, flags);
|
|
|
if (!substream->opened)
|
|
|
- return -EBADFD;
|
|
|
- count = snd_rawmidi_transmit_peek(substream, buffer, count);
|
|
|
- if (count < 0)
|
|
|
- return count;
|
|
|
- return snd_rawmidi_transmit_ack(substream, count);
|
|
|
+ result = -EBADFD;
|
|
|
+ else {
|
|
|
+ count = __snd_rawmidi_transmit_peek(substream, buffer, count);
|
|
|
+ if (count <= 0)
|
|
|
+ result = count;
|
|
|
+ else
|
|
|
+ result = __snd_rawmidi_transmit_ack(substream, count);
|
|
|
+ }
|
|
|
+ spin_unlock_irqrestore(&runtime->lock, flags);
|
|
|
+ return result;
|
|
|
}
|
|
|
EXPORT_SYMBOL(snd_rawmidi_transmit);
|
|
|
|