2006/8/14, Markus Rechberger <mrechberger@xxxxxxxxx>:
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