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