[PATCH v4] sound: rawmidi: Add framing mode

David Henningsson coding at diwic.se
Mon Apr 12 21:32:37 CEST 2021


On 2021-04-12 11:54, Takashi Iwai wrote:
> On Sat, 10 Apr 2021 14:02:29 +0200,
> David Henningsson wrote:
>> +struct snd_rawmidi_framing_tstamp {
>> +	/* For now, frame_type is always 0. Midi 2.0 is expected to add new
>> +	 * types here. Applications are expected to skip unknown frame types.
>> +	 */
>> +	unsigned char frame_type;
>> +	unsigned char length; /* number of valid bytes in data field */
>> +	unsigned char reserved[2];
>> +	unsigned int tv_nsec;		/* nanoseconds */
>> +	unsigned long long tv_sec;	/* seconds */
> Please use u32 and u64 here instead of int and long long.
> We really want to be specific about the field types.
>
>> +static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream,
>> +			const unsigned char *buffer, int src_count, struct timespec64 *tstamp)
> Pass const to tstamp.
>
>> +{
>> +	struct snd_rawmidi_runtime *runtime = substream->runtime;
>> +	struct snd_rawmidi_framing_tstamp *dest_ptr;
>> +	struct snd_rawmidi_framing_tstamp frame = { .tv_sec = tstamp->tv_sec, .tv_nsec = tstamp->tv_nsec };
>> +
>> +	int dest_frames = 0;
>> +	int frame_size = sizeof(struct snd_rawmidi_framing_tstamp);
>> +
>> +	if (snd_BUG_ON(runtime->hw_ptr & 0x1f || runtime->buffer_size & 0x1f || frame_size != 0x20))
> The frame_size check should be rather BUILD_BUG_ON() as it's constant.
> And the buffer_size check is... well, not sure whether we need here.
> snd_BUG_ON() is performed even if there is no debug option set (but
> the debug message is suppressed).
>
>> +		return -EINVAL;
>> +	while (src_count > 0) {
>> +		if ((int)(runtime->buffer_size - runtime->avail) < frame_size) {
>> +			runtime->xruns += src_count;
>> +			return dest_frames * frame_size;
> Better to break the loop for unifying the exit path.
>
>> @@ -987,8 +1035,15 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
>>   			  "snd_rawmidi_receive: input is not active!!!\n");
>>   		return -EINVAL;
>>   	}
>> -	spin_lock_irqsave(&runtime->lock, flags);
>> -	if (count == 1) {	/* special case, faster code */
>> +	if (substream->framing == SNDRV_RAWMIDI_FRAMING_TSTAMP) {
>> +		if (substream->clock_type == CLOCK_MONOTONIC_RAW)
>> +			ktime_get_raw_ts64(&ts64);
>> +		else
>> +			ktime_get_ts64(&ts64);
>> +		spin_lock_irqsave(&runtime->lock, flags);
>> +		result = receive_with_tstamp_framing(substream, buffer, count, &ts64);
>> +	} else if (count == 1) {	/* special case, faster code */
>> +		spin_lock_irqsave(&runtime->lock, flags);
>>   		substream->bytes++;
>>   		if (runtime->avail < runtime->buffer_size) {
>>   			runtime->buffer[runtime->hw_ptr++] = buffer[0];
>> @@ -999,6 +1054,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
>>   			runtime->xruns++;
>>   		}
>>   	} else {
>> +		spin_lock_irqsave(&runtime->lock, flags);
>>   		substream->bytes += count;
>>   		count1 = runtime->buffer_size - runtime->hw_ptr;
>>   		if (count1 > count)
> It's error-prone to put the spin_lock_irqsave() in various places.
> If you want to get the timestamp outside the spinlock inevitably, just
> do it before the spin_lock_irqsave() line,
>
> 	if (substream->framing == SNDRV_RAWMIDI_FRAMING_TSTAMP) {
> 		if (substream->clock_type == CLOCK_MONOTONIC_RAW)
> 			ktime_get_raw_ts64(&ts64);
> 		else
> 			ktime_get_ts64(&ts64);
> 	}

Thanks for the review.

I'll refactor this part into a separate function. The rest I'll just fix 
the way you suggest.

>
> 	spin_lock_irqsave(&runtime->lock, flags);
> 	if (substream->framing == SNDRV_RAWMIDI_FRAMING_TSTAMP) {
> 		....
> 	} else if (count == 1) {	/* special case, faster code */
> 		....
>
> And, the patch misses the change in rawmidi_compat.c.  It's also the
> reason we'd like to avoid the bit fields usage, too.  (Not only that,
> though.)
>
> One thing I'm considering is how to inform the current framing and the
> timestamp mode to user-space.  Currently we have only the ioctl to set
> the values but not to inquiry.

Yes, this is the same as we do with PCM. There is no ioctl to get 
current hw/sw params either.

> Should we put those new information into the info or the status ioctl?

I would prefer neither, because it is not necessary and creates an 
inconsistency with PCM.

> If so, it might be also helpful to inform the frame byte size
> explicitly there, instead of assuming only a constant.

If userspace has verified the kernel protocol version and successfully 
calledSNDRV_RAWMIDI_IOCTL_PARAMS with the framing byte/bitfield/whatever 
set, then userspace can be sure that the frames are according to the 
snd_rawmidi_framing_tstamp struct. Knowing the frame byte size but not 
knowing the exact format is of no use to userspace anyway, right?

// David


More information about the Alsa-devel mailing list