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);