total_packs = (period_bytes + maxsize - 1) / maxsize; 
unsigned int minsize; /* determine how small a packet can be */ minsize = (subs->freqn >> (16 - subs->datainterval)) * (frame_bits >> 3); /* with sync from device, assume it can be 25% lower */ if (subs->syncpipe) minsize -= minsize >> 2; minsize = max(minsize, 1u); total_packs = (period_bytes + minsize - 1) / minsize; 
static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_bytes,			       unsigned int rate, unsigned int frame_bits){	unsigned int maxsize, n, i;	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;	unsigned int npacks[MAX_URBS], urb_packs, total_packs;	/* calculate the frequency in 16.16 format */	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)		subs->freqn = get_usb_full_speed_rate(rate);	else		subs->freqn = get_usb_high_speed_rate(rate);	subs->freqm = subs->freqn;	/* calculate max. frequency */	if (subs->maxpacksize) {		/* whatever fits into a max. size packet */		maxsize = subs->maxpacksize;		subs->freqmax = (maxsize / (frame_bits >> 3))				<< (16 - subs->datainterval);	} else {		/* no max. packet size: just take 25% higher than nominal */		subs->freqmax = subs->freqn + (subs->freqn >> 2);		maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))				>> (16 - subs->datainterval);	}	subs->phase = 0;	if (subs->fill_max)		subs->curpacksize = subs->maxpacksize;	else		subs->curpacksize = maxsize;	if (is_playback)		urb_packs = nrpacks;	else		urb_packs = 1;	if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)		urb_packs = (urb_packs * 8) >> subs->datainterval;	/* allocate a temporary buffer for playback */	if (is_playback) {		subs->tmpbuf = kmalloc(maxsize * urb_packs, GFP_KERNEL);		if (! subs->tmpbuf) {			snd_printk(KERN_ERR "cannot malloc tmpbuf\n");			return -ENOMEM;		}	}	/* decide how many packets to be used */	if (is_playback) {		total_packs = (period_bytes + maxsize - 1) / maxsize;		if (total_packs < 2 * MIN_PACKS_URB)			total_packs = 2 * MIN_PACKS_URB;	} else {		total_packs = MAX_URBS * urb_packs;	}	subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;	if (subs->nurbs > MAX_URBS) {		/* too much... */		subs->nurbs = MAX_URBS;		total_packs = MAX_URBS * urb_packs;	}	n = total_packs;	for (i = 0; i < subs->nurbs; i++) {		npacks[i] = n > urb_packs ? urb_packs : n;		n -= urb_packs;	}	if (subs->nurbs <= 1) {		/* too little - we need at least two packets		 * to ensure contiguous playback/capture		 */		subs->nurbs = 2;		npacks[0] = (total_packs + 1) / 2;		npacks[1] = total_packs - npacks[0];	} else if (npacks[subs->nurbs-1] < MIN_PACKS_URB) {		/* the last packet is too small.. */		if (subs->nurbs > 2) {			/* merge to the first one */			npacks[0] += npacks[subs->nurbs - 1];			subs->nurbs--;		} else {			/* divide to two */			subs->nurbs = 2;			npacks[0] = (total_packs + 1) / 2;			npacks[1] = total_packs - npacks[0];		}	}	/* allocate and initialize data urbs */	for (i = 0; i < subs->nurbs; i++) {		snd_urb_ctx_t *u = &subs->dataurb[i];		u->index = i;		u->subs = subs;		u->transfer = 0;		u->packets = npacks[i];		if (subs->fmt_type == USB_FORMAT_TYPE_II)			u->packets++; /* for transfer delimiter */		if (! is_playback) {			/* allocate a capture buffer per urb */			u->buf = kmalloc(maxsize * u->packets, GFP_KERNEL);			if (! u->buf) {				release_substream_urbs(subs, 0);				return -ENOMEM;			}		}		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);		if (! u->urb) {			release_substream_urbs(subs, 0);			return -ENOMEM;		}		u->urb->dev = subs->dev;		u->urb->pipe = subs->datapipe;		u->urb->transfer_flags = URB_ISO_ASAP;		u->urb->number_of_packets = u->packets;		u->urb->interval = 1 << subs->datainterval;		u->urb->context = u;		u->urb->complete = snd_usb_complete_callback(snd_complete_urb);	}	if (subs->syncpipe) {		/* allocate and initialize sync urbs */		for (i = 0; i < SYNC_URBS; i++) {			snd_urb_ctx_t *u = &subs->syncurb[i];			u->index = i;			u->subs = subs;			u->packets = 1;			u->urb = usb_alloc_urb(1, GFP_KERNEL);			if (! u->urb) {				release_substream_urbs(subs, 0);				return -ENOMEM;			}			u->urb->transfer_buffer = subs->syncbuf + i * 4;			u->urb->transfer_buffer_length = 4;			u->urb->dev = subs->dev;			u->urb->pipe = subs->syncpipe;			u->urb->transfer_flags = URB_ISO_ASAP;			u->urb->number_of_packets = 1;			u->urb->interval = 1 << subs->syncinterval;			u->urb->context = u;			u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);		}	}	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/d6db392e9235c48bb945624798e9beede7b85b12/usbaudio.c/buggy/sound/usb/usbaudio.c