Re: Line6 TonePort

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

    .buffer_bytes_max    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2,
    .period_bytes_min    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2,
    .period_bytes_max    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2,

I don't know what value TONEPORT_48000_24_PACKET_SIZE_OUT is _BUT_
I had to take care about this in my driver too.
The max packet size is 128 bytes, but I'm only allowed to fill 18-20 bytes.
Theoretically I could submit 2560 bytes within one urb but as soon as
I submit more than 384 bytes or less I get a buzz or choppy sound.
Have a look at the windows usbsnoop logs again.

Here's the code of my usb audio driver:
http://kurzlink.de/sBMLkXGXe

Markus

On 8/14/06, Stefano D'Angelo <zanga.mail@xxxxxxxxx> wrote:
> Clemens you were right of course, what I was saying was just bull shit (and
> I'm sorry).
> However the problem remains... I really don't know what's wrong with my code
> so I post the "interesting parts" here. Please help, I DO need this card to
> work!
>
> static snd_pcm_hardware_t snd_toneport_playback_hw = {
>     .info            = SNDRV_PCM_INFO_MMAP |
>                   SNDRV_PCM_INFO_INTERLEAVED |
>                   SNDRV_PCM_INFO_BLOCK_TRANSFER |
>                   SNDRV_PCM_INFO_MMAP_VALID,
>     .formats        = SNDRV_PCM_FMTBIT_S16_LE |
>                   SNDRV_PCM_FMTBIT_S24_3LE,
>     .rates            = SNDRV_PCM_RATE_44100 |
>                   SNDRV_PCM_RATE_48000,
>     .rate_min        = 44100,
>     .rate_max        = 48000,
>     .channels_min        = 2,
>     .channels_max        = 2,
>     .buffer_bytes_max    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2,
>     .period_bytes_min    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2,
>     .period_bytes_max    = TONEPORT_48000_24_PACKET_SIZE_OUT * 2,
>     .periods_min        = 1,
>     .periods_max        = 2
> };
>
> Here period_bytes_min are is as the maximum period size to use just one PCM.
>
> #define snd_toneport_period_elapsed(old, new) \
>     (new >= TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2) || \
>     ((old < TONEPORT_48000_24_PACKET_SIZE_OUT * 2) && \
>      (new >= TONEPORT_48000_24_PACKET_SIZE_OUT * 2))
>
> This one should test if a period is elapsed based on the old playback
> position (I see other drivers call such pointers hwptr) and the new one
> (before this last is "normalized").
>
> /*
>  * null urb trasfer's completition callback
>  */
> static void snd_toneport_playback_complete_first(struct urb* urb,
>         struct pt_regs* regs)
> {
>     snd_pcm_substream_t *substream = (snd_pcm_substream_t *)(urb->context);
>     snd_pcm_runtime_t *runtime = substream->runtime;
>     struct snd_toneport *chip = snd_pcm_substream_chip(substream);
>
>     memcpy(urb->transfer_buffer, runtime->dma_area,
>             chip->playback_packet_size * 2);
>
>     urb->complete = snd_toneport_playback_complete;
>
>     usb_submit_urb(urb, GFP_ATOMIC);
> }
>
> /*
>  * playback transfers' completition callback
>  */
> static void snd_toneport_playback_complete(struct urb* urb,
>         struct pt_regs* regs)
> {
>     snd_pcm_substream_t *substream = (snd_pcm_substream_t *)(urb->context);
>     snd_pcm_runtime_t *runtime = substream->runtime;
>     struct snd_toneport *chip = snd_pcm_substream_chip(substream);
>     int new_pos = chip->playback_pos + chip->playback_packet_size * 2;
>     int offs;
>
>     if (new_pos <= TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2) {
>         memcpy(urb->transfer_buffer,
>                 runtime->dma_area + chip->playback_pos,
>                 chip->playback_packet_size * 2);
>     } else {
>         offs = TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2 -
>             chip->playback_pos;
>         memcpy(urb->transfer_buffer,
>                 runtime->dma_area + chip->playback_pos,
>                 offs);
>         memcpy(urb->transfer_buffer + new_pos,
>                 runtime->dma_area,
>                 chip->playback_packet_size * 2 - offs);
>     }
>
>     if (snd_toneport_period_elapsed(chip->playback_pos, new_pos)) {
>         if (new_pos >= TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2)
>             new_pos -= TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2;
>         chip->playback_pos = new_pos;
>         snd_pcm_period_elapsed(substream);
>     } else {
>         chip->playback_pos = new_pos;
>     }
>
>     if (chip->status & TONEPORT_STATUS_PLAYBACK)
>         usb_submit_urb(urb, GFP_ATOMIC);
> }
>
> /*
>  * hw_params callback
>  *
>  * TODO: capture and full duplex
>  */
> static int snd_toneport_pcm_hw_params(snd_pcm_substream_t *substream,
>         snd_pcm_hw_params_t *hw_params)
> {
>     struct snd_toneport *chip = snd_pcm_substream_chip(substream);
>     unsigned char msg[] = TONEPORT_MSG_3;
>     int alt, err;
>
>     alt = (params_format(hw_params) == SNDRV_PCM_FORMAT_S16_LE) ? 1 : 3;
>     if ((params_rate(hw_params) == 44100))
>         alt++;
>
>     if ((err = usb_set_interface(chip->dev, 0, alt)) < 0)
>         return err;
>     chip->altsetting = alt;
>
>     if ((err = snd_toneport_submit_control_transfer(chip->dev, msg)) < 0)
>         return err;
>
>     chip->playback_packet_size = out_sizes[alt - 1];
>     if (!chip->playback_urb) {
>         chip->playback_urb = usb_alloc_urb(2, GFP_KERNEL);
>         chip->playback_urb->dev = chip->dev;
>         chip->playback_urb->pipe = usb_sndisocpipe(chip->dev, 1);
>         chip->playback_urb->context = substream;
>         chip->playback_urb->transfer_flags = URB_ISO_ASAP |
>             URB_NO_TRANSFER_DMA_MAP;
>         chip->playback_urb->interval = 1;
>         chip->playback_urb->number_of_packets = 2;
>         chip->playback_urb->iso_frame_desc[0].offset = 0;
>     } else {
>         usb_buffer_free(chip->dev, chip->playback_packet_size * 2,
>                 chip->playback_urb->transfer_buffer,
>                 chip->playback_urb->transfer_dma);
>     }
>     if (!(chip->playback_urb->transfer_buffer =
>         usb_buffer_alloc(chip->dev, chip->playback_packet_size * 2,
>             GFP_KERNEL, &chip->playback_urb->transfer_dma)))
>         return -ENOMEM;
>     chip->playback_urb->transfer_buffer_length =
>         chip->playback_packet_size * 2;
>     chip->playback_urb->iso_frame_desc[0].length =
>         chip->playback_urb->iso_frame_desc[1].offset =
>         chip->playback_urb->iso_frame_desc[1].length =
>         chip->playback_packet_size;
>
>     return snd_pcm_lib_malloc_pages(substream,
>             TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2);
> }
>
> /*
>  * trigger callback
>  */
> static int snd_toneport_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
> {
>     struct snd_toneport *chip = snd_pcm_substream_chip(substream);
>
>     switch (cmd) {
>     case SNDRV_PCM_TRIGGER_START:
>         memset(chip->playback_urb->transfer_buffer, 0,
>                 chip->playback_packet_size * 2);
>         chip->playback_pos = 0;
>         chip->status |= TONEPORT_STATUS_PLAYBACK;
>         chip->playback_urb->complete =
>             snd_toneport_playback_complete_first;
>         return usb_submit_urb(chip->playback_urb, GFP_ATOMIC);
>         break;
>     case SNDRV_PCM_TRIGGER_STOP:
>         chip->status &= ~TONEPORT_STATUS_PLAYBACK;
>         break;
>     default:
>             return -EINVAL;
>         break;
>     }
>
>     return 0;
> }
>
> /*
>  * pointer callback
>  */
> static snd_pcm_uframes_t snd_toneport_pcm_pointer(
>         snd_pcm_substream_t* substream)
> {
>     struct snd_toneport *chip = snd_pcm_substream_chip(substream);
>
>     return bytes_to_frames(substream->runtime, chip->playback_pos);
> }
>
> As you can see I chose to store the playback position in bytes instead of
> frames because I have 6-bytes frames and 4-bytes frames (depends on the
> format).
> Also TONEPORT_48000_24_PACKET_SIZE_OUT * 2 * 2 is the alsa buffer size.
> Thanks,
>
> Stefano
>
>


-- 
Markus Rechberger

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux