1 /* 2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * 20 * File: usbpipe.c 21 * 22 * Purpose: Handle USB control endpoint 23 * 24 * Author: Warren Hsu 25 * 26 * Date: Mar. 29, 2005 27 * 28 * Functions: 29 * CONTROLnsRequestOut - Write variable length bytes to MEM/BB/MAC/EEPROM 30 * CONTROLnsRequestIn - Read variable length bytes from MEM/BB/MAC/EEPROM 31 * ControlvWriteByte - Write one byte to MEM/BB/MAC/EEPROM 32 * ControlvReadByte - Read one byte from MEM/BB/MAC/EEPROM 33 * ControlvMaskByte - Read one byte from MEM/BB/MAC/EEPROM and clear/set some bits in the same address 34 * 35 * Revision History: 36 * 04-05-2004 Jerry Chen: Initial release 37 * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,ControlvMaskByte 38 * 39 */ 40 41 #include "int.h" 42 #include "rxtx.h" 43 #include "dpc.h" 44 #include "control.h" 45 #include "desc.h" 46 #include "device.h" 47 48 /*--------------------- Static Definitions -------------------------*/ 49 //endpoint def 50 //endpoint 0: control 51 //endpoint 1: interrupt 52 //endpoint 2: read bulk 53 //endpoint 3: write bulk 54 55 //RequestType: 56 //#define REQUEST_OUT (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) // 0x40 57 //#define REQUEST_IN (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE ) //0xc0 58 //static int msglevel =MSG_LEVEL_DEBUG; 59 static int msglevel =MSG_LEVEL_INFO; 60 61 62 #define USB_CTL_WAIT 500 //ms 63 64 #ifndef URB_ASYNC_UNLINK 65 #define URB_ASYNC_UNLINK 0 66 #endif 67 68 /*--------------------- Static Classes ----------------------------*/ 69 70 /*--------------------- Static Variables --------------------------*/ 71 72 /*--------------------- Static Functions --------------------------*/ 73 static 74 void 75 s_nsInterruptUsbIoCompleteRead( 76 struct urb *urb 77 ); 78 79 80 static 81 void 82 s_nsBulkInUsbIoCompleteRead( 83 struct urb *urb 84 ); 85 86 87 static 88 void 89 s_nsBulkOutIoCompleteWrite( 90 struct urb *urb 91 ); 92 93 94 static 95 void 96 s_nsControlInUsbIoCompleteRead( 97 struct urb *urb 98 ); 99 100 static 101 void 102 s_nsControlInUsbIoCompleteWrite( 103 struct urb *urb 104 ); 105 106 /*--------------------- Export Variables --------------------------*/ 107 108 /*--------------------- Export Functions --------------------------*/ 109 110 int PIPEnsControlOutAsyn( 111 PSDevice pDevice, 112 BYTE byRequest, 113 WORD wValue, 114 WORD wIndex, 115 WORD wLength, 116 PBYTE pbyBuffer 117 ) 118 { 119 int ntStatus; 120 121 if (pDevice->Flags & fMP_DISCONNECTED) 122 return STATUS_FAILURE; 123 124 if (pDevice->Flags & fMP_CONTROL_WRITES) 125 return STATUS_FAILURE; 126 127 if (in_interrupt()) { 128 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest); 129 return STATUS_FAILURE; 130 } 131 132 ntStatus = usb_control_msg( 133 pDevice->usb, 134 usb_sndctrlpipe(pDevice->usb , 0), 135 byRequest, 136 0x40, // RequestType 137 wValue, 138 wIndex, 139 (void *) pbyBuffer, 140 wLength, 141 HZ 142 ); 143 if (ntStatus >= 0) { 144 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus); 145 ntStatus = 0; 146 } else { 147 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus); 148 } 149 150 return ntStatus; 151 } 152 153 int PIPEnsControlOut( 154 PSDevice pDevice, 155 BYTE byRequest, 156 WORD wValue, 157 WORD wIndex, 158 WORD wLength, 159 PBYTE pbyBuffer 160 ) 161 { 162 int ntStatus = 0; 163 int ii; 164 165 if (pDevice->Flags & fMP_DISCONNECTED) 166 return STATUS_FAILURE; 167 168 if (pDevice->Flags & fMP_CONTROL_WRITES) 169 return STATUS_FAILURE; 170 171 pDevice->sUsbCtlRequest.bRequestType = 0x40; 172 pDevice->sUsbCtlRequest.bRequest = byRequest; 173 pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); 174 pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); 175 pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); 176 pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; 177 pDevice->pControlURB->actual_length = 0; 178 // Notice, pbyBuffer limited point to variable buffer, can't be constant. 179 usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, 180 usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, 181 pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice); 182 183 ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); 184 if (ntStatus != 0) { 185 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus); 186 return STATUS_FAILURE; 187 } 188 else { 189 MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); 190 } 191 spin_unlock_irq(&pDevice->lock); 192 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { 193 194 if (pDevice->Flags & fMP_CONTROL_WRITES) 195 mdelay(1); 196 else 197 break; 198 199 if (ii >= USB_CTL_WAIT) { 200 DBG_PRT(MSG_LEVEL_DEBUG, 201 KERN_INFO "control send request submission timeout\n"); 202 spin_lock_irq(&pDevice->lock); 203 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); 204 return STATUS_FAILURE; 205 } 206 } 207 spin_lock_irq(&pDevice->lock); 208 209 return STATUS_SUCCESS; 210 } 211 212 int PIPEnsControlIn( 213 PSDevice pDevice, 214 BYTE byRequest, 215 WORD wValue, 216 WORD wIndex, 217 WORD wLength, 218 PBYTE pbyBuffer 219 ) 220 { 221 int ntStatus = 0; 222 int ii; 223 224 if (pDevice->Flags & fMP_DISCONNECTED) 225 return STATUS_FAILURE; 226 227 if (pDevice->Flags & fMP_CONTROL_READS) 228 return STATUS_FAILURE; 229 230 pDevice->sUsbCtlRequest.bRequestType = 0xC0; 231 pDevice->sUsbCtlRequest.bRequest = byRequest; 232 pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); 233 pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex); 234 pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength); 235 pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK; 236 pDevice->pControlURB->actual_length = 0; 237 usb_fill_control_urb(pDevice->pControlURB, pDevice->usb, 238 usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest, 239 pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice); 240 241 ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); 242 if (ntStatus != 0) { 243 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus); 244 }else { 245 MP_SET_FLAG(pDevice, fMP_CONTROL_READS); 246 } 247 248 spin_unlock_irq(&pDevice->lock); 249 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { 250 251 if (pDevice->Flags & fMP_CONTROL_READS) 252 mdelay(1); 253 else 254 break; 255 256 if (ii >= USB_CTL_WAIT) { 257 DBG_PRT(MSG_LEVEL_DEBUG, 258 KERN_INFO "control rcv request submission timeout\n"); 259 spin_lock_irq(&pDevice->lock); 260 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); 261 return STATUS_FAILURE; 262 } 263 } 264 spin_lock_irq(&pDevice->lock); 265 266 return ntStatus; 267 } 268 269 static 270 void 271 s_nsControlInUsbIoCompleteWrite( 272 struct urb *urb 273 ) 274 { 275 PSDevice pDevice; 276 277 pDevice = urb->context; 278 switch (urb->status) { 279 case 0: 280 break; 281 case -EINPROGRESS: 282 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status); 283 break; 284 case -ENOENT: 285 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status); 286 break; 287 default: 288 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status); 289 } 290 291 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); 292 } 293 294 295 296 /* 297 * Description: 298 * Complete function of usb Control callback 299 * 300 * Parameters: 301 * In: 302 * pDevice - Pointer to the adapter 303 * 304 * Out: 305 * none 306 * 307 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 308 * 309 */ 310 static 311 void 312 s_nsControlInUsbIoCompleteRead( 313 struct urb *urb 314 ) 315 { 316 PSDevice pDevice; 317 318 pDevice = urb->context; 319 switch (urb->status) { 320 case 0: 321 break; 322 case -EINPROGRESS: 323 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status); 324 break; 325 case -ENOENT: 326 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status); 327 break; 328 default: 329 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status); 330 } 331 332 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); 333 } 334 335 336 337 338 /* 339 * Description: 340 * Allocates an usb interrupt in irp and calls USBD. 341 * 342 * Parameters: 343 * In: 344 * pDevice - Pointer to the adapter 345 * Out: 346 * none 347 * 348 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 349 * 350 */ 351 int PIPEnsInterruptRead(PSDevice pDevice) 352 { 353 int ntStatus = STATUS_FAILURE; 354 355 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n"); 356 357 if(pDevice->intBuf.bInUse == TRUE){ 358 return (STATUS_FAILURE); 359 } 360 pDevice->intBuf.bInUse = TRUE; 361 // pDevice->bEventAvailable = FALSE; 362 pDevice->ulIntInPosted++; 363 364 // 365 // Now that we have created the urb, we will send a 366 // request to the USB device object. 367 // 368 pDevice->pInterruptURB->interval = pDevice->int_interval; 369 370 usb_fill_bulk_urb(pDevice->pInterruptURB, 371 pDevice->usb, 372 usb_rcvbulkpipe(pDevice->usb, 1), 373 (void *) pDevice->intBuf.pDataBuf, 374 MAX_INTERRUPT_SIZE, 375 s_nsInterruptUsbIoCompleteRead, 376 pDevice); 377 378 ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC); 379 if (ntStatus != 0) { 380 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus); 381 } 382 383 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus); 384 return ntStatus; 385 } 386 387 388 /* 389 * Description: 390 * Complete function of usb interrupt in irp. 391 * 392 * Parameters: 393 * In: 394 * pDevice - Pointer to the adapter 395 * 396 * Out: 397 * none 398 * 399 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 400 * 401 */ 402 static 403 void 404 s_nsInterruptUsbIoCompleteRead( 405 struct urb *urb 406 ) 407 408 { 409 PSDevice pDevice; 410 int ntStatus; 411 412 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n"); 413 // 414 // The context given to IoSetCompletionRoutine is the receive buffer object 415 // 416 pDevice = (PSDevice)urb->context; 417 418 // 419 // We have a number of cases: 420 // 1) The USB read timed out and we received no data. 421 // 2) The USB read timed out and we received some data. 422 // 3) The USB read was successful and fully filled our irp buffer. 423 // 4) The irp was cancelled. 424 // 5) Some other failure from the USB device object. 425 // 426 ntStatus = urb->status; 427 428 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus); 429 430 // if we were not successful, we need to free the int buffer for future use right here 431 // otherwise interrupt data handler will free int buffer after it handle it. 432 if (( ntStatus != STATUS_SUCCESS )) { 433 pDevice->ulBulkInError++; 434 pDevice->intBuf.bInUse = FALSE; 435 436 // if (ntStatus == USBD_STATUS_CRC) { 437 // pDevice->ulIntInContCRCError++; 438 // } 439 440 // if (ntStatus == STATUS_NOT_CONNECTED ) 441 // { 442 pDevice->fKillEventPollingThread = TRUE; 443 // } 444 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus ); 445 } else { 446 pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length; 447 pDevice->ulIntInContCRCError = 0; 448 pDevice->bEventAvailable = TRUE; 449 INTnsProcessData(pDevice); 450 } 451 452 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus); 453 454 455 if (pDevice->fKillEventPollingThread != TRUE) { 456 usb_fill_bulk_urb(pDevice->pInterruptURB, 457 pDevice->usb, 458 usb_rcvbulkpipe(pDevice->usb, 1), 459 (void *) pDevice->intBuf.pDataBuf, 460 MAX_INTERRUPT_SIZE, 461 s_nsInterruptUsbIoCompleteRead, 462 pDevice); 463 464 ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC); 465 if (ntStatus != 0) { 466 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus); 467 } 468 } 469 // 470 // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion 471 // routine (IofCompleteRequest) will stop working on the irp. 472 // 473 return ; 474 } 475 476 /* 477 * Description: 478 * Allocates an usb BulkIn irp and calls USBD. 479 * 480 * Parameters: 481 * In: 482 * pDevice - Pointer to the adapter 483 * Out: 484 * none 485 * 486 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 487 * 488 */ 489 int PIPEnsBulkInUsbRead(PSDevice pDevice, PRCB pRCB) 490 { 491 int ntStatus = 0; 492 struct urb *pUrb; 493 494 495 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n"); 496 497 if (pDevice->Flags & fMP_DISCONNECTED) 498 return STATUS_FAILURE; 499 500 pDevice->ulBulkInPosted++; 501 502 503 pUrb = pRCB->pUrb; 504 // 505 // Now that we have created the urb, we will send a 506 // request to the USB device object. 507 // 508 if (pRCB->skb == NULL) { 509 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n"); 510 return ntStatus; 511 } 512 513 usb_fill_bulk_urb(pUrb, 514 pDevice->usb, 515 usb_rcvbulkpipe(pDevice->usb, 2), 516 (void *) (pRCB->skb->data), 517 MAX_TOTAL_SIZE_WITH_ALL_HEADERS, 518 s_nsBulkInUsbIoCompleteRead, 519 pRCB); 520 521 ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC); 522 if (ntStatus != 0) { 523 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus); 524 return STATUS_FAILURE ; 525 } 526 pRCB->Ref = 1; 527 pRCB->bBoolInUse= TRUE; 528 529 return ntStatus; 530 } 531 532 533 534 535 /* 536 * Description: 537 * Complete function of usb BulkIn irp. 538 * 539 * Parameters: 540 * In: 541 * pDevice - Pointer to the adapter 542 * 543 * Out: 544 * none 545 * 546 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 547 * 548 */ 549 static 550 void 551 s_nsBulkInUsbIoCompleteRead( 552 struct urb *urb 553 ) 554 555 { 556 PRCB pRCB = (PRCB)urb->context; 557 PSDevice pDevice = (PSDevice)pRCB->pDevice; 558 unsigned long bytesRead; 559 BOOL bIndicateReceive = FALSE; 560 BOOL bReAllocSkb = FALSE; 561 int status; 562 563 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n"); 564 status = urb->status; 565 bytesRead = urb->actual_length; 566 567 if (status) { 568 pDevice->ulBulkInError++; 569 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status); 570 571 pDevice->scStatistic.RxFcsErrCnt ++; 572 //todo...xxxxxx 573 // if (status == USBD_STATUS_CRC) { 574 // pDevice->ulBulkInContCRCError++; 575 // } 576 // if (status == STATUS_DEVICE_NOT_CONNECTED ) 577 // { 578 // MP_SET_FLAG(pDevice, fMP_DISCONNECTED); 579 // } 580 } else { 581 bIndicateReceive = TRUE; 582 pDevice->ulBulkInContCRCError = 0; 583 pDevice->ulBulkInBytesRead += bytesRead; 584 585 pDevice->scStatistic.RxOkCnt ++; 586 } 587 588 589 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status); 590 591 if (bIndicateReceive) { 592 spin_lock(&pDevice->lock); 593 if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE) 594 bReAllocSkb = TRUE; 595 spin_unlock(&pDevice->lock); 596 } 597 pRCB->Ref--; 598 if (pRCB->Ref == 0) 599 { 600 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList); 601 spin_lock(&pDevice->lock); 602 RXvFreeRCB(pRCB, bReAllocSkb); 603 spin_unlock(&pDevice->lock); 604 } 605 606 607 return; 608 } 609 610 /* 611 * Description: 612 * Allocates an usb BulkOut irp and calls USBD. 613 * 614 * Parameters: 615 * In: 616 * pDevice - Pointer to the adapter 617 * Out: 618 * none 619 * 620 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver 621 * 622 */ 623 int 624 PIPEnsSendBulkOut( 625 PSDevice pDevice, 626 PUSB_SEND_CONTEXT pContext 627 ) 628 { 629 int status; 630 struct urb *pUrb; 631 632 633 634 pDevice->bPWBitOn = FALSE; 635 636 /* 637 if (pDevice->pPendingBulkOutContext != NULL) { 638 pDevice->NumContextsQueued++; 639 EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext); 640 status = STATUS_PENDING; 641 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n"); 642 return status; 643 } 644 */ 645 646 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n"); 647 648 if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) { 649 650 pUrb = pContext->pUrb; 651 pDevice->ulBulkOutPosted++; 652 // pDevice->pPendingBulkOutContext = pContext; 653 usb_fill_bulk_urb( 654 pUrb, 655 pDevice->usb, 656 usb_sndbulkpipe(pDevice->usb, 3), 657 (void *) &(pContext->Data[0]), 658 pContext->uBufLen, 659 s_nsBulkOutIoCompleteWrite, 660 pContext); 661 662 status = usb_submit_urb(pUrb, GFP_ATOMIC); 663 if (status != 0) 664 { 665 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status); 666 return STATUS_FAILURE; 667 } 668 return STATUS_PENDING; 669 } 670 else { 671 pContext->bBoolInUse = FALSE; 672 return STATUS_RESOURCES; 673 } 674 } 675 676 /* 677 * Description: s_nsBulkOutIoCompleteWrite 678 * 1a) Indicate to the protocol the status of the write. 679 * 1b) Return ownership of the packet to the protocol. 680 * 681 * 2) If any more packets are queue for sending, send another packet 682 * to USBD. 683 * If the attempt to send the packet to the driver fails, 684 * return ownership of the packet to the protocol and 685 * try another packet (until one succeeds). 686 * 687 * Parameters: 688 * In: 689 * pdoUsbDevObj - pointer to the USB device object which 690 * completed the irp 691 * pIrp - the irp which was completed by the 692 * device object 693 * pContext - the context given to IoSetCompletionRoutine 694 * before calling IoCallDriver on the irp 695 * The pContext is a pointer to the USB device object. 696 * Out: 697 * none 698 * 699 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine 700 * (IofCompleteRequest) to stop working on the irp. 701 * 702 */ 703 static 704 void 705 s_nsBulkOutIoCompleteWrite( 706 struct urb *urb 707 ) 708 { 709 PSDevice pDevice; 710 int status; 711 CONTEXT_TYPE ContextType; 712 unsigned long ulBufLen; 713 PUSB_SEND_CONTEXT pContext; 714 715 716 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n"); 717 // 718 // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct 719 // 720 pContext = (PUSB_SEND_CONTEXT) urb->context; 721 ASSERT( NULL != pContext ); 722 723 pDevice = pContext->pDevice; 724 ContextType = pContext->Type; 725 ulBufLen = pContext->uBufLen; 726 727 if (!netif_device_present(pDevice->dev)) 728 return; 729 730 // 731 // Perform various IRP, URB, and buffer 'sanity checks' 732 // 733 734 status = urb->status; 735 //we should have failed, succeeded, or cancelled, but NOT be pending 736 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status); 737 738 if(status == STATUS_SUCCESS) { 739 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen); 740 pDevice->ulBulkOutBytesWrite += ulBufLen; 741 pDevice->ulBulkOutContCRCError = 0; 742 pDevice->nTxDataTimeCout = 0; 743 744 } else { 745 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status); 746 pDevice->ulBulkOutError++; 747 } 748 749 // pDevice->ulCheckForHangCount = 0; 750 // pDevice->pPendingBulkOutContext = NULL; 751 752 if ( CONTEXT_DATA_PACKET == ContextType ) { 753 // Indicate to the protocol the status of the sent packet and return 754 // ownership of the packet. 755 if (pContext->pPacket != NULL) { 756 dev_kfree_skb_irq(pContext->pPacket); 757 pContext->pPacket = NULL; 758 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx %d bytes\n",(int)ulBufLen); 759 } 760 761 pDevice->dev->trans_start = jiffies; 762 763 764 if (status == STATUS_SUCCESS) { 765 pDevice->packetsSent++; 766 } 767 else { 768 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status); 769 pDevice->packetsSentDropped++; 770 } 771 772 } 773 if (pDevice->bLinkPass == TRUE) { 774 if (netif_queue_stopped(pDevice->dev)) 775 netif_wake_queue(pDevice->dev); 776 } 777 pContext->bBoolInUse = FALSE; 778 779 return; 780 } 781