r5u870

Ricoh R5U870 Linux Driver
git clone https://logand.com/git/r5u870.git/
Log | Files | Refs | README | LICENSE

usbcam_util.c (25013B)


      1 /*
      2  * USBCAM abstraction library for USB webcam drivers
      3  *
      4  * Copyright (c) 2007 Sam Revitch <samr7 cs washington edu>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2, or (at your option)
      9  * any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     19  */
     20 
     21 #include "usbcam_priv.h"
     22 
     23 /*
     24  * This file contains utility routines, including:
     25  * - usbcam_choose_altsetting() for selecting int/isoc altsettings
     26  * - The usbcam_urbstream accessory module
     27  * - usbcam_hexdump() buffer dumping utility function
     28  *
     29  * TODO:
     30  * - Find some way to alert minidrivers of URB shortages
     31  */
     32 
     33 /*
     34  * Traverse the alternate setting list and find one that provides
     35  * the least bandwidth that satisfies the minimum requirement.
     36  */
     37 int usbcam_choose_altsetting(struct usbcam_dev *udp, int ifnum,
     38 			     int pipe, int bytes_per_sec_min,
     39 			     int pkt_min, int pkt_max,
     40 			     int *altsetting_nr)
     41 {
     42 	struct usb_interface *intf;
     43 	const struct usb_host_interface *aintf;
     44 	const struct usb_endpoint_descriptor *epd = NULL;
     45 	int i, j;
     46 
     47 	int wmp, bw;
     48 	int best_alt = -1, best_alt_bw = 0;
     49 
     50 	usbcam_chklock(udp);
     51 
     52 	if (udp->ud_disconnected) {
     53 		usbcam_warn(udp, "%s: device is disconnected", __FUNCTION__);
     54 		return -ENODEV;
     55 	}
     56 
     57 	if (ifnum < 0)
     58 		ifnum = udp->ud_intf->cur_altsetting->desc.bInterfaceNumber;
     59 
     60 	intf = usb_ifnum_to_if(udp->ud_dev, ifnum);
     61 	if (!intf) {
     62 		usbcam_warn(udp, "%s: interface %d does not exist",
     63 			    __FUNCTION__, ifnum);
     64 		return -ENODEV;
     65 	}
     66 
     67 	if ((bytes_per_sec_min >= 0) &&
     68 	    !usb_pipeisoc(pipe) && !usb_pipeint(pipe)) {
     69 		usbcam_warn(udp, "%s: minidriver specified bytes_per_sec_min "
     70 			    "on non-iso non-int pipe", __FUNCTION__);
     71 	}
     72 
     73 	for (i = 0; i < intf->num_altsetting; i++) {
     74 
     75 		aintf = &intf->altsetting[i];
     76 		for (j = 0; j < aintf->desc.bNumEndpoints; j++) {
     77 			epd = &aintf->endpoint[j].desc;
     78 			if ((epd->bEndpointAddress &
     79 			     USB_ENDPOINT_NUMBER_MASK) ==
     80 			    usb_pipeendpoint(pipe))
     81 				break;
     82 		}
     83 
     84 		if (j == aintf->desc.bNumEndpoints) {
     85 			/* Desired endpoint not present in this descriptor */
     86 			usbcam_dbg(udp, ALTSETTING,
     87 				   "altsetting %d has no EP%d",
     88 				   i, usb_pipeendpoint(pipe));
     89 			continue;
     90 		}
     91 
     92 		if (((usb_pipetype(pipe) == PIPE_ISOCHRONOUS) &&
     93 		     !usb_endpoint_xfer_isoc(epd)) ||
     94 		    ((usb_pipetype(pipe) == PIPE_INTERRUPT) &&
     95 		     !usb_endpoint_xfer_int(epd)) ||
     96 		    (usb_pipein(pipe) && !usb_endpoint_dir_in(epd)) ||
     97 		    (!usb_pipein(pipe) && usb_endpoint_dir_in(epd))) {
     98 			/* Something is horribly wrong */
     99 			usbcam_dbg(udp, ALTSETTING,
    100 				   "altsetting %d has unexpected EP%d",
    101 				   i, usb_pipeendpoint(pipe));
    102 			continue;
    103 		}
    104 
    105 		bw = 0;
    106 		wmp = le16_to_cpu(epd->wMaxPacketSize);
    107 
    108 		/* Bandwidth only applies to iso & int pipes */
    109 		if (usb_pipeisoc(pipe) || usb_pipeint(pipe)) {
    110 			if (udp->ud_dev->speed == USB_SPEED_HIGH) {
    111 				/* 8 uframes per regular frame */
    112 				bw = 8000;
    113 
    114 				/* high bandwidth endpoint? */
    115 				wmp = ((wmp & 0x7ff) *
    116 				       (((wmp >> 11) & 0x3) + 1));
    117 			} else {
    118 				bw = 1000;
    119 				wmp &= 0x7ff;
    120 			}
    121 
    122 			bw *= wmp;
    123 
    124 			/* Divide by interval / frame skippage */
    125 			bw = bw / (1 << (epd->bInterval - 1));
    126 
    127 			usbcam_dbg(udp, ALTSETTING,
    128 				   "altsetting %d provides %d B/s bandwidth",
    129 				   i, bw);
    130 
    131 			/* Check the bandwidth */
    132 			if (bw < bytes_per_sec_min)
    133 				continue;
    134 
    135 		} else
    136 			wmp &= 0x7ff;
    137 
    138 		/* Check the packet size */
    139 		if (((pkt_min >= 0) && (wmp < pkt_min)) ||
    140 		    ((pkt_max >= 0) && (wmp > pkt_max)))
    141 			continue;
    142 
    143 		if ((best_alt < 0) || (bw < best_alt_bw)) {
    144 			best_alt = i;
    145 			best_alt_bw = bw;
    146 		}
    147 	}
    148 
    149 	if (best_alt == -1)
    150 		return -ENODEV;
    151 
    152 	*altsetting_nr = best_alt;
    153 	return 0;
    154 }
    155 USBCAM_EXPORT_SYMBOL(usbcam_choose_altsetting);
    156 
    157 
    158 /*
    159  * DMA buffer helper routines
    160  */
    161 static int usbcam_urb_allocbuf(struct urb *urbp, size_t nbytes)
    162 {
    163 	urbp->transfer_buffer = usb_buffer_alloc(urbp->dev,
    164 						 nbytes,
    165 						 GFP_KERNEL,
    166 						 &urbp->transfer_dma);
    167 	if (!urbp->transfer_buffer)
    168 		return -ENOMEM;
    169 
    170 	urbp->transfer_buffer_length = nbytes;
    171 	urbp->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    172 	return 0;
    173 }
    174 
    175 static inline void usbcam_urb_freebuf(struct urb *urbp)
    176 {
    177 	usb_buffer_free(urbp->dev,
    178 			urbp->transfer_buffer_length,
    179 			urbp->transfer_buffer,
    180 			urbp->transfer_dma);
    181 }
    182 
    183 struct urb *usbcam_urb_alloc(struct usbcam_dev *udp, int pipe,
    184 			     int pktsize, int npkts, int alloc_buf)
    185 {
    186 	struct urb *urbp;
    187 	int nbytes, i;
    188 
    189 	if (npkts) {
    190 		if (!usb_pipeisoc(pipe)) {
    191 			usbcam_err(udp, "npkts=%d but !pipeisoc", npkts);
    192 			return NULL;
    193 		}
    194 	} else if (usb_pipeisoc(pipe)) {
    195 		usbcam_err(udp, "npkts=0 but pipeisoc");
    196 		return NULL;
    197 	}
    198 
    199 
    200 	urbp = usb_alloc_urb(npkts, GFP_KERNEL);
    201 	if (!urbp)
    202 		return NULL;
    203 
    204 	urbp->dev = udp->ud_dev;
    205 	urbp->pipe = pipe;
    206 	urbp->number_of_packets = npkts;
    207 	urbp->transfer_buffer = NULL;
    208 	urbp->transfer_buffer_length = 0;
    209 
    210 	if (alloc_buf) {
    211 		nbytes = pktsize;
    212 		if (npkts)
    213 			nbytes *= npkts;
    214 
    215 		if (usbcam_urb_allocbuf(urbp, nbytes)) {
    216 			usb_free_urb(urbp);
    217 			return NULL;
    218 		}
    219 	}
    220 
    221 	if (npkts)
    222 		urbp->transfer_flags |= URB_ISO_ASAP;
    223 
    224 	for (i = 0; i < npkts; i++) {
    225 		urbp->iso_frame_desc[i].offset = (i * pktsize);
    226 		urbp->iso_frame_desc[i].length = pktsize;
    227 		urbp->iso_frame_desc[i].actual_length = 0;
    228 		urbp->iso_frame_desc[i].status = 0;
    229 	}
    230 
    231 	return urbp;
    232 }
    233 USBCAM_EXPORT_SYMBOL(usbcam_urb_alloc);
    234 
    235 void usbcam_urb_free(struct urb *urbp, int free_buf)
    236 {
    237 	if (free_buf)
    238 		usbcam_urb_freebuf(urbp);
    239 	usb_free_urb(urbp);
    240 }
    241 USBCAM_EXPORT_SYMBOL(usbcam_urb_free);
    242 
    243 
    244 /*
    245  * Streaming request helper functions
    246  * This depends on the other usbcam stuff, but they don't depend on it,
    247  * and it should be considered an extension sub-library.
    248  */
    249 
    250 /* Default parameters for config_iso and config_bulk */
    251 #define USBCAM_DFL_ISO_REQS		8
    252 #define USBCAM_DFL_ISO_URB_PKTS		32
    253 
    254 #define USBCAM_DFL_BULK_REQS		8
    255 
    256 
    257 /*
    258  * This structure represents a set of USB requests - URBs and buffers
    259  */
    260 struct usbcam_urbinfo {
    261 	struct list_head		ib_links;
    262 	struct usbcam_urbstream		*ib_urbstream;
    263 	struct task_struct		**ib_worker;
    264 	struct usbcam_workitem		ib_workitem;
    265 	struct timer_list		ib_timeout;
    266 	unsigned short			ib_nurbs;
    267 	unsigned short			ib_cururb;
    268 	struct urb			*ib_urbs[0];
    269 };
    270 
    271 /* usp->us_lock must be held on entry */
    272 static void usbcam_urbstream_resubmit(struct usbcam_urbstream *usp,
    273 				      struct usbcam_urbinfo *ibp)
    274 {
    275 	int res;
    276 
    277 	if (!ibp->ib_cururb) {
    278 		list_del(&ibp->ib_links);
    279 		list_add(&ibp->ib_links, &usp->us_active_list);
    280 		usp->us_active_count++;
    281 	}
    282 
    283 	res = usb_submit_urb(ibp->ib_urbs[ibp->ib_cururb], GFP_ATOMIC);
    284 	if (res == -EL2NSYNC)
    285 		res = usb_submit_urb(ibp->ib_urbs[ibp->ib_cururb], GFP_ATOMIC);
    286 
    287 	if (res) {
    288  		usbcam_dbg(usp->us_dev, URBSTREAM,
    289 			   "urbstream[%d] resubmit %p/%d failed: %d",
    290 			   usp->us_endpoint, ibp, ibp->ib_cururb, res);
    291 		usp->us_resubmit_err = res;
    292 
    293 		ibp->ib_cururb = 0;
    294 		list_del(&ibp->ib_links);
    295 		list_add(&ibp->ib_links, &usp->us_unused_list);
    296 		if (!--usp->us_active_count)
    297 			complete(&usp->us_active_empty);
    298 
    299 		(void) usbcam_work_queue(&usp->us_error_workitem);
    300 	}
    301 
    302 	else if (usp->us_timeout_ticks) {
    303 		ibp->ib_timeout.expires = jiffies + usp->us_timeout_ticks;
    304 		add_timer(&ibp->ib_timeout);
    305 	}
    306 }
    307 
    308 /* usp->us_lock NOT held on entry */
    309 static int usbcam_urbstream_submit_unused(struct usbcam_urbstream *usp)
    310 {
    311 	struct usbcam_urbinfo *ibp = NULL;
    312 	long flags;
    313 	int res;
    314 
    315 	spin_lock_irqsave(&usp->us_lock, flags);
    316 
    317 	if (!list_empty(&usp->us_unused_list)) {
    318 		ibp = list_entry(usp->us_unused_list.next,
    319 				 struct usbcam_urbinfo, ib_links);
    320 		list_del(&ibp->ib_links);
    321 		list_add_tail(&ibp->ib_links, &usp->us_active_list);
    322 		usp->us_active_count++;
    323 		ibp->ib_cururb = 0;
    324 	}
    325 
    326 	spin_unlock_irqrestore(&usp->us_lock, flags);
    327 
    328 	if (!ibp)
    329 		return -ENOENT;
    330 
    331 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] urb submit %p/%d",
    332 		   usp->us_endpoint, ibp, ibp->ib_cururb);
    333 	res = usb_submit_urb(ibp->ib_urbs[ibp->ib_cururb], GFP_KERNEL);
    334 	if (res == -EL2NSYNC)
    335 		res = usb_submit_urb(ibp->ib_urbs[ibp->ib_cururb], GFP_KERNEL);
    336 
    337 	if (!res && usp->us_timeout_ticks) {
    338 		ibp->ib_timeout.expires = jiffies + usp->us_timeout_ticks;
    339 		add_timer(&ibp->ib_timeout);
    340 	}
    341 
    342 	if (res) {
    343 		usbcam_dbg(usp->us_dev, URBSTREAM, "%s: URB submit failed: %d",
    344 			   __FUNCTION__, res);
    345 		spin_lock_irqsave(&usp->us_lock, flags);
    346 		list_del(&ibp->ib_links);
    347 		list_add_tail(&ibp->ib_links, &usp->us_unused_list);
    348 		assert(usp->us_active_count > 0);
    349 		usp->us_active_count--;
    350 		spin_unlock_irqrestore(&usp->us_lock, flags);
    351 	}
    352 
    353 	return res;
    354 }
    355 
    356 
    357 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
    358 static void usbcam_urbstream_urb_complete(struct urb *urb)
    359 #else
    360 static void usbcam_urbstream_urb_complete(struct urb *urb,
    361 					  struct pt_regs *unused)
    362 #endif
    363 {
    364 	struct usbcam_urbinfo *ibp = (struct usbcam_urbinfo *) urb->context;
    365 	struct usbcam_urbstream *usp = ibp->ib_urbstream;
    366 	long flags;
    367 	int timer_fired = 0, res;
    368 
    369 	assert(ibp->ib_urbs[ibp->ib_cururb] == urb);
    370 
    371 	if (usp->us_timeout_ticks)
    372 		timer_fired = !del_timer_sync(&ibp->ib_timeout);
    373 
    374 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] urb complete: %p/%d",
    375 		   usp->us_endpoint, ibp, ibp->ib_cururb);
    376 
    377 	spin_lock_irqsave(&usp->us_lock, flags);
    378 
    379 	if (list_empty(&ibp->ib_links)) {
    380 		/* We are being singled out for cancelation, do nothing */
    381 		usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] "
    382 			   "request canceled, ignoring", usp->us_endpoint);
    383 		goto done;
    384 	}
    385 
    386 	ibp->ib_cururb++;
    387 	if (!urb->status) {
    388 		if (ibp->ib_cururb != ibp->ib_nurbs) {
    389 			usbcam_urbstream_resubmit(usp, ibp);
    390 			goto done;
    391 		}
    392 	}
    393 
    394 	/* Move to the done queue, submit a new URB, wake */
    395 	list_del(&ibp->ib_links);
    396 	list_add_tail(&ibp->ib_links, &usp->us_complete_list);
    397 	assert(usp->us_active_count > 0);
    398 	usp->us_active_count--;
    399 
    400 	if ((urb->status == -ECONNRESET) && timer_fired) {
    401 		usbcam_dbg(usp->us_dev, URBSTREAM,
    402 			   "urbstream[%d] urb %p/%d timed out",
    403 			   usp->us_endpoint, ibp, ibp->ib_cururb);
    404 		urb->status = -ETIMEDOUT;
    405 	}
    406 
    407 	res = usbcam_work_queue(&ibp->ib_workitem);
    408 	if (res) {
    409 		assert(res == -EBUSY);
    410 		list_del(&ibp->ib_links);
    411 		list_add_tail(&ibp->ib_links, &usp->us_unused_list);
    412 		goto done;
    413 	}
    414 
    415 	if (usp->us_resubmit_err) {
    416 		usbcam_dbg(usp->us_dev, URBSTREAM,
    417 			   "urbstream[%d] not resubmitting, pending error",
    418 			   usp->us_endpoint);
    419 		goto done;
    420 	}
    421 
    422 	/* Is the active count sufficient? */
    423 	if (usp->us_active_count >= usp->us_active_goal)
    424 		goto done;
    425 
    426 	/* Should we automatically submit an URB from the unused list? */
    427 	if (usp->us_streaming) {
    428 		if (list_empty(&usp->us_unused_list)) {
    429 			usbcam_dbg(usp->us_dev, URBSTREAM,
    430 				   "urbstream[%d] not resubmitting, "
    431 				   "URBs exhausted",
    432 				   usp->us_endpoint);
    433 			goto done;
    434 		}
    435 
    436 		ibp = list_entry(usp->us_unused_list.next,
    437 				 struct usbcam_urbinfo, ib_links);
    438 
    439 		ibp->ib_cururb = 0;
    440 		usbcam_urbstream_resubmit(usp, ibp);
    441 	}
    442 
    443 done:
    444 	if (!usp->us_active_count)
    445 		complete(&usp->us_active_empty);
    446 	spin_unlock_irqrestore(&usp->us_lock, flags);
    447 }
    448 
    449 static void usbcam_urbstream_urb_timeout(unsigned long data)
    450 {
    451 	struct usbcam_urbinfo *ibp = (struct usbcam_urbinfo *) data;
    452 	usb_unlink_urb(ibp->ib_urbs[ibp->ib_cururb]);
    453 }
    454 
    455 static void usbcam_urbstream_req_done(struct usbcam_urbinfo *ibp)
    456 {
    457 	struct usbcam_urbstream *usp;
    458 	long flags;
    459 
    460 	usp = ibp->ib_urbstream;
    461 	spin_lock_irqsave(&usp->us_lock, flags);
    462 
    463 	if (usp->us_streaming &&
    464 	    (usp->us_active_count < usp->us_active_goal)) {
    465 		/* Try to limp along with underflows */
    466 		ibp->ib_cururb = 0;
    467 		usbcam_urbstream_resubmit(usp, ibp);
    468 
    469 	} else {
    470 		list_del(&ibp->ib_links);
    471 		list_add(&ibp->ib_links, &usp->us_unused_list);
    472 	}
    473 
    474 	spin_unlock_irqrestore(&usp->us_lock, flags);
    475 }
    476 
    477 static void usbcam_urbstream_freereq(struct usbcam_urbinfo *ibp)
    478 {
    479 	int i;
    480 	assert(list_empty(&ibp->ib_links));
    481 	for (i = 0; i < ibp->ib_nurbs; i++)
    482 		usbcam_urb_free(ibp->ib_urbs[i], 1);
    483 	kfree(ibp);
    484 }
    485 
    486 static struct usbcam_urbinfo *
    487 usbcam_urbstream_allocreq(struct usbcam_urbstream *usp, int pipe, int ival,
    488 			  int pktlen, int npkts, int alloc)
    489 {
    490 	struct usbcam_urbinfo *ibp;
    491 	int sizeremain, nurbs, cpktlen;
    492 	int i;
    493 
    494 	usbcam_chklock(usp->us_dev);
    495 
    496 	sizeremain = 0;
    497 	nurbs = 1;
    498 	if (usb_pipebulk(pipe)) {
    499 		sizeremain = npkts;
    500 		npkts = 0;
    501 		nurbs = (sizeremain + pktlen - 1) / pktlen;
    502 	}
    503 
    504 	ibp = kzalloc(sizeof(*ibp) + (nurbs * sizeof(struct urb *)),
    505 		      GFP_KERNEL);
    506 	if (!ibp)
    507 		return NULL;
    508 
    509 	INIT_LIST_HEAD(&ibp->ib_links);
    510 	ibp->ib_urbstream = usp;
    511 	ibp->ib_nurbs = nurbs;
    512 
    513 	for (i = 0; i < nurbs; i++) {
    514 		cpktlen = pktlen;
    515 		if (sizeremain && (cpktlen > sizeremain))
    516 			cpktlen = sizeremain;
    517 		ibp->ib_urbs[i] = usbcam_urb_alloc(usp->us_dev, pipe, cpktlen,
    518 						   npkts, alloc);
    519 
    520 		if (!ibp->ib_urbs[i])
    521 			break;
    522 
    523 		ibp->ib_urbs[i]->complete = usbcam_urbstream_urb_complete;
    524 		ibp->ib_urbs[i]->interval = ival;
    525 		ibp->ib_urbs[i]->context = ibp;
    526 
    527 
    528 		if (sizeremain)
    529 			sizeremain -= cpktlen;
    530 	}
    531 
    532 	if (i < nurbs) {
    533 		while (i--)
    534 			usbcam_urb_free(ibp->ib_urbs[i], alloc);
    535 		kfree(ibp);
    536 		return NULL;
    537 	}
    538 
    539 	setup_timer(&ibp->ib_timeout,
    540 		    usbcam_urbstream_urb_timeout,
    541 		    (unsigned long) ibp);
    542 
    543 	return ibp;
    544 }
    545 
    546 static void usbcam_urbstream_freereqs(struct list_head *head)
    547 {
    548 	struct usbcam_urbinfo *ibp;
    549 	while (!list_empty(head)) {
    550 		ibp = list_entry(head->next, struct usbcam_urbinfo, ib_links);
    551 		list_del_init(&ibp->ib_links);
    552 		usbcam_urbstream_freereq(ibp);
    553 	}
    554 }
    555 
    556 static void usbcam_urbstream_error(struct usbcam_workitem *work)
    557 {
    558 	struct usbcam_urbstream *usp = container_of(work,
    559 						     struct usbcam_urbstream,
    560 						     us_error_workitem);
    561 	unsigned long flags;
    562 	int sts;
    563 
    564 	spin_lock_irqsave(&usp->us_lock, flags);
    565 	sts = usp->us_resubmit_err;
    566 	usp->us_resubmit_err = 0;
    567 	spin_unlock_irqrestore(&usp->us_lock, flags);
    568 
    569 	if (sts && usp->us_ops && usp->us_ops->submit_error)
    570 		usp->us_ops->submit_error(usp->us_dev, usp, sts);
    571 }
    572 
    573 void usbcam_urbstream_init(struct usbcam_urbstream *usp,
    574 			   struct usbcam_dev *udp, int ep)
    575 {
    576 	memset(usp, 0, sizeof(*usp));
    577 	usp->us_dev = udp;
    578 	usp->us_endpoint = ep;
    579 	spin_lock_init(&usp->us_lock);
    580 	INIT_LIST_HEAD(&usp->us_unused_list);
    581 	INIT_LIST_HEAD(&usp->us_active_list);
    582 	INIT_LIST_HEAD(&usp->us_complete_list);
    583 	init_completion(&usp->us_active_empty);
    584 	usbcam_work_init(usp->us_dev,
    585 			 &usp->us_error_workitem,
    586 			 usbcam_urbstream_error);
    587 }
    588 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_init);
    589 
    590 void usbcam_urbstream_stop(struct usbcam_urbstream *usp, int wait)
    591 {
    592 	long flags;
    593 	struct usbcam_urbinfo *ibp, *prev;
    594 	int res;
    595 
    596 	usbcam_chklock(usp->us_dev);
    597 
    598 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] stopping",
    599 		   usp->us_endpoint);
    600 	spin_lock_irqsave(&usp->us_lock, flags);
    601 
    602 	if (usp->us_streaming)
    603 		usp->us_streaming = 0;
    604 
    605 	if (!wait) {
    606 		/*
    607 		 * Cancel all in-flight requests without waiting
    608 		 */
    609 		while (!list_empty(&usp->us_active_list)) {
    610 			ibp = list_entry(usp->us_active_list.prev,
    611 					 struct usbcam_urbinfo, ib_links);
    612 			list_del_init(&ibp->ib_links);
    613 			assert(usp->us_active_count > 0);
    614 			usp->us_active_count--;
    615 			spin_unlock_irqrestore(&usp->us_lock, flags);
    616 			usb_kill_urb(ibp->ib_urbs[ibp->ib_cururb]);
    617 			spin_lock_irqsave(&usp->us_lock, flags);
    618 			list_add(&ibp->ib_links, &usp->us_unused_list);
    619 		}
    620 	} else {
    621 		/*
    622 		 * Wait for all in-flight request groups to complete
    623 		 * Do so while holding the device mutex, which is a bit ugly
    624 		 */
    625 		while (!list_empty(&usp->us_active_list)) {
    626 			init_completion(&usp->us_active_empty);
    627 			spin_unlock_irqrestore(&usp->us_lock, flags);
    628 			wait_for_completion(&usp->us_active_empty);
    629 			spin_lock_irqsave(&usp->us_lock, flags);
    630 		}
    631 	}
    632 
    633 
    634 	/* Cancel all completed request groups with queued work items */
    635 	list_for_each_entry_safe(ibp, prev,
    636 				 &usp->us_complete_list,
    637 				 ib_links) {
    638 
    639 		res = usbcam_work_cancel(&ibp->ib_workitem);
    640 
    641 		if (!ibp->ib_worker)
    642 			assert(!res);
    643 		else {
    644 			assert(res);
    645 			assert(*ibp->ib_worker == current);
    646 			*ibp->ib_worker = NULL;
    647 			ibp->ib_worker = NULL;
    648 		}
    649 
    650 		list_del(&ibp->ib_links);
    651 		list_add_tail(&ibp->ib_links, &usp->us_unused_list);
    652 	}
    653 
    654 	/* Cancel the error work item */
    655 	(void) usbcam_work_cancel(&usp->us_error_workitem);
    656 
    657 	/* Clear the resubmission error code */
    658 	usp->us_resubmit_err = 0;
    659 
    660 	spin_unlock_irqrestore(&usp->us_lock, flags);
    661 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] stopped",
    662 		   usp->us_endpoint);
    663 }
    664 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_stop);
    665 
    666 int usbcam_urbstream_start(struct usbcam_urbstream *usp)
    667 {
    668 	struct usbcam_dev *udp;
    669 	long flags;
    670 	int submitted = 0, res;
    671 
    672 	udp = usp->us_dev;
    673 
    674 	usbcam_chklock(udp);
    675 
    676 	spin_lock_irqsave(&usp->us_lock, flags);
    677 	if (usp->us_streaming) {
    678 		spin_unlock_irqrestore(&usp->us_lock, flags);
    679 		usbcam_warn(udp, "%s: urbstream[%d] already streaming",
    680 			    __FUNCTION__, usp->us_endpoint);
    681 		return -EEXIST;
    682 	}
    683 
    684 	if (list_empty(&usp->us_unused_list)) {
    685 		usbcam_warn(udp, "%s urbstream[%d] no unused URBs",
    686 			    __FUNCTION__, usp->us_endpoint);
    687 		return -ENOENT;
    688 	}
    689 
    690 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] starting",
    691 		   usp->us_endpoint);
    692 	usp->us_streaming = 1;
    693 
    694 	spin_unlock_irqrestore(&usp->us_lock, flags);
    695 
    696 	/* Submit initial URB(s) */
    697 	while (1) {
    698 		res = usbcam_urbstream_submit_unused(usp);
    699 		assert(res != -ENOENT);
    700 		if (res) {
    701 			usbcam_urbstream_stop(usp, 0);
    702 			return res;
    703 		}
    704 
    705 		if (++submitted == usp->us_active_goal)
    706 			break;
    707 	}
    708 
    709 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] started",
    710 		   usp->us_endpoint);
    711 	return 0;
    712 
    713 }
    714 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_start);
    715 
    716 int usbcam_urbstream_submit_one(struct usbcam_urbstream *usp)
    717 {
    718 	usbcam_chklock(usp->us_dev);
    719 	assert(!usp->us_streaming);
    720 	return usbcam_urbstream_submit_unused(usp);
    721 }
    722 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_submit_one);
    723 
    724 void usbcam_urbstream_cleanup(struct usbcam_urbstream *usp)
    725 {
    726 	usbcam_urbstream_stop(usp, 0);
    727 	usbcam_urbstream_freereqs(&usp->us_unused_list);
    728 	assert(list_empty(&usp->us_active_list));
    729 	assert(list_empty(&usp->us_complete_list));
    730 }
    731 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_cleanup);
    732 
    733 
    734 static void usbcam_urbstream_iso_process(struct usbcam_workitem *work)
    735 {
    736 	struct usbcam_urbinfo *ibp = container_of(work, struct usbcam_urbinfo,
    737 						 ib_workitem);
    738 	struct usbcam_urbstream *usp = ibp->ib_urbstream;
    739 	struct task_struct *me = current;
    740 	struct urb *urbp;
    741 	int i;
    742 
    743 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] processing %p",
    744 		   usp->us_endpoint, ibp);
    745 
    746 	assert(!ibp->ib_worker);
    747 	ibp->ib_worker = &me;
    748 
    749 	urbp = ibp->ib_urbs[0];
    750 	for (i = 0; i < urbp->number_of_packets; i++) {
    751 		char *buf = (((char *) urbp->transfer_buffer) +
    752 			     urbp->iso_frame_desc[i].offset);
    753 		int len = urbp->iso_frame_desc[i].actual_length;
    754 		int status = urbp->iso_frame_desc[i].status;
    755 
    756 		urbp->iso_frame_desc[i].actual_length = 0;
    757 		urbp->iso_frame_desc[i].status = 0;
    758 
    759 		usp->us_ops->packet_done(usp->us_dev,
    760 					 usp, buf, len, status);
    761 		if (!me)
    762 			return;
    763 	}
    764 
    765 	assert(ibp->ib_worker == &me);
    766 	ibp->ib_worker = NULL;
    767 
    768 	usbcam_urbstream_req_done(ibp);
    769 }
    770 
    771 static int usbcam_urbstream_allocreqs_isorcv(struct usbcam_urbstream *usp,
    772 					     struct list_head *head, int count,
    773 					     int ival, int pktcount,
    774 					     int pktlen)
    775 {
    776 	struct usbcam_urbinfo *ibp;
    777 	struct list_head new_bufs;
    778 	int pipe;
    779 
    780 	pipe = usb_rcvisocpipe(usp->us_dev->ud_dev, usp->us_endpoint);
    781 
    782 	INIT_LIST_HEAD(&new_bufs);
    783 
    784 	while (count--) {
    785 		ibp = usbcam_urbstream_allocreq(usp, pipe, ival,
    786 						pktlen, pktcount, 1);
    787 		if (!ibp) {
    788 			usbcam_urbstream_freereqs(&new_bufs);
    789 			return -ENOMEM;
    790 		}
    791 
    792 		usbcam_work_init(usp->us_dev,
    793 				 &ibp->ib_workitem,
    794 				 usbcam_urbstream_iso_process);
    795 		list_add_tail(&ibp->ib_links, &new_bufs);
    796 	}
    797 
    798 	list_splice(&new_bufs, head);
    799 	return 0;
    800 }
    801 
    802 int usbcam_urbstream_config_iso(struct usbcam_urbstream *usp,
    803 				const struct usbcam_urbstream_ops *ops,
    804 				int pktcount, int nreqs, int interval,
    805 				int pktlen)
    806 {
    807 	int res;
    808 
    809 	usbcam_urbstream_cleanup(usp);
    810 
    811 	usp->us_active_goal = 2;
    812 	usp->us_ops = ops;
    813 
    814 	if (!interval) {
    815 		/* FIXME: find the appropriate interval for the endpoint */
    816 		return -EINVAL;
    817 	}
    818 
    819 	if (!pktlen) {
    820 		/* Choose a packet length based on the current altsetting */
    821 		pktlen = usb_maxpacket(usp->us_dev->ud_dev,
    822 				       usb_rcvisocpipe(usp->us_dev->ud_dev,
    823 						       usp->us_endpoint), 0);
    824 		if (!pktlen) {
    825 			usbcam_dbg(usp->us_dev, URBSTREAM,
    826 				   "urbstream[%d]: current altsetting has "
    827 				   "maxpacket=0", usp->us_endpoint);
    828 			return -EINVAL;
    829 		}
    830 		if (usp->us_dev->ud_dev->speed == USB_SPEED_HIGH)
    831 			pktlen = (pktlen & 0x7ff) *
    832 				(((pktlen >> 11) & 0x3) + 1);
    833 		else
    834 			pktlen &= 0x7ff;
    835 
    836 		usbcam_dbg(usp->us_dev, URBSTREAM,
    837 			   "urbstream[%d] using pktlen %d",
    838 			   usp->us_endpoint, pktlen);
    839 	}
    840 
    841 	if (!pktcount)
    842 		pktcount = USBCAM_DFL_ISO_URB_PKTS;
    843 	if (!nreqs)
    844 		nreqs = USBCAM_DFL_ISO_REQS;
    845 	if (nreqs < usp->us_active_goal) {
    846 		usbcam_warn(usp->us_dev, "%s urbstream[%d]: at least %d reqs "
    847 			    "are required", __FUNCTION__, usp->us_endpoint,
    848 			    usp->us_active_goal);
    849 		nreqs = usp->us_active_goal;
    850 	}
    851 
    852 	usp->us_timeout_ticks = 0;
    853 
    854 	res = usbcam_urbstream_allocreqs_isorcv(usp, &usp->us_unused_list,
    855 						nreqs, interval, pktcount,
    856 						pktlen);
    857 	return res;
    858 }
    859 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_config_iso);
    860 
    861 
    862 static void usbcam_urbstream_bulk_process(struct usbcam_workitem *work)
    863 {
    864 	struct usbcam_urbinfo *ibp = container_of(work, struct usbcam_urbinfo,
    865 						 ib_workitem);
    866 	struct usbcam_urbstream *usp = ibp->ib_urbstream;
    867 	struct task_struct *me = current;
    868 	struct urb *urbp;
    869 	int len, status;
    870 	int i;
    871 
    872 	usbcam_dbg(usp->us_dev, URBSTREAM, "urbstream[%d] processing %p",
    873 		   usp->us_endpoint, ibp);
    874 
    875 	assert(!ibp->ib_worker);
    876 	ibp->ib_worker = &me;
    877 
    878 	for (i = 0; i < ibp->ib_cururb; i++) {
    879 		urbp = ibp->ib_urbs[i];
    880 		len = urbp->actual_length;
    881 		status = urbp->status;
    882 
    883 		urbp->actual_length = 0;
    884 		urbp->status = 0;
    885 
    886 		usp->us_ops->packet_done(usp->us_dev, usp,
    887 					 urbp->transfer_buffer, len, status);
    888 		if (!me)
    889 			return;
    890 	}
    891 
    892 	assert(ibp->ib_worker == &me);
    893 	ibp->ib_worker = NULL;
    894 
    895 	usbcam_urbstream_req_done(ibp);
    896 }
    897 
    898 static int usbcam_urbstream_allocreqs_bulkrcv(struct usbcam_urbstream *usp,
    899 					      struct list_head *head,
    900 					      int count, int reqlen,
    901 					      int maxpkt)
    902 {
    903 	struct usbcam_urbinfo *ibp;
    904 	struct list_head new_bufs;
    905 	int pipe;
    906 
    907 	pipe = usb_rcvbulkpipe(usp->us_dev->ud_dev, usp->us_endpoint);
    908 
    909 	INIT_LIST_HEAD(&new_bufs);
    910 
    911 	while (count--) {
    912 		ibp = usbcam_urbstream_allocreq(usp, pipe, 0,
    913 						maxpkt, reqlen, 1);
    914 		if (!ibp) {
    915 			usbcam_urbstream_freereqs(&new_bufs);
    916 			return -ENOMEM;
    917 		}
    918 
    919 		usbcam_work_init(usp->us_dev,
    920 				 &ibp->ib_workitem,
    921 				 usbcam_urbstream_bulk_process);
    922 		list_add_tail(&ibp->ib_links, &new_bufs);
    923 	}
    924 
    925 	list_splice(&new_bufs, head);
    926 	return 0;
    927 }
    928 
    929 int usbcam_urbstream_config_bulk(struct usbcam_urbstream *usp,
    930 				 const struct usbcam_urbstream_ops *ops,
    931 				 int nreqs, int reqlen, int maxpkt,
    932 				 int timeout_ms)
    933 {
    934 	int res;
    935 
    936 	usbcam_urbstream_cleanup(usp);
    937 
    938 	usp->us_active_goal = 1;
    939 	usp->us_ops = ops;
    940 
    941 	if (!maxpkt)
    942 		maxpkt = 64 * 1024;
    943 	if (reqlen < 0) {
    944 		usbcam_dbg(usp->us_dev, URBSTREAM,
    945 			   "urbstream[%d]: packet length must be >=0",
    946 			   usp->us_endpoint);
    947 		return -EINVAL;
    948 	}
    949 
    950 	if (!nreqs)
    951 		nreqs = USBCAM_DFL_BULK_REQS;
    952 	if (nreqs < usp->us_active_goal) {
    953 		usbcam_warn(usp->us_dev, "%s urbstream[%d]: at least %d URBs "
    954 			    "are required", __FUNCTION__, usp->us_endpoint,
    955 			usp->us_active_goal);
    956 		nreqs = usp->us_active_goal;
    957 	}
    958 
    959 	usp->us_timeout_ticks = (timeout_ms * HZ) / 1000;
    960 
    961 	res = usbcam_urbstream_allocreqs_bulkrcv(usp, &usp->us_unused_list,
    962 						 nreqs, reqlen, maxpkt);
    963 	return res;
    964 }
    965 USBCAM_EXPORT_SYMBOL(usbcam_urbstream_config_bulk);
    966 
    967 
    968 #ifdef usbcam_hexdump
    969 #undef usbcam_hexdump
    970 #endif
    971 #define dumpable_char(X) (((X) >= ' ') && ((X) <= '~'))
    972 void usbcam_hexdump(struct usbcam_dev *udp, const u8 *buf, size_t len)
    973 {
    974 	const int bpl = 16;
    975 	const int cend_max = ((bpl * 4) + 1);
    976 	static const char n2x[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
    977 				      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    978 	char x, outbuf[cend_max + 1];
    979 	unsigned int cstart, cend, xpos, cpos, offset;
    980 
    981 	offset = 0;
    982 	cstart = (3 * bpl) + 1;
    983 	cend = cstart + bpl;
    984 	outbuf[cend] = '\0';
    985 	goto beginning;
    986 
    987 	while (len) {
    988 		x = *buf++;
    989 		outbuf[xpos++] = n2x[(x >> 4) & 0xf];
    990 		outbuf[xpos++] = n2x[x & 0xf];
    991 		outbuf[cpos+cstart] = dumpable_char(x) ? x : '.';
    992 		cpos++;
    993 		xpos++;
    994 		len--;
    995 
    996 		if (!len || (cpos == bpl)) {
    997 			printk(KERN_DEBUG "%s: %08x %s\n",
    998 			       udp->ud_dev_name, offset, outbuf);
    999 			offset += bpl;
   1000 
   1001 		beginning:
   1002 			memset(outbuf, ' ', cend);
   1003 			cpos = 0;
   1004 			xpos = 0;
   1005 		}
   1006 	}
   1007 }
   1008 USBCAM_EXPORT_SYMBOL(usbcam_hexdump);