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
PIPEnsControlOutAsyn(PSDevice pDevice,BYTE byRequest,WORD wValue,WORD wIndex,WORD wLength,PBYTE pbyBuffer)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
PIPEnsControlOut(PSDevice pDevice,BYTE byRequest,WORD wValue,WORD wIndex,WORD wLength,PBYTE pbyBuffer)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 if (pDevice->Flags & fMP_CONTROL_READS)
172 return STATUS_FAILURE;
173
174 MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
175
176 pDevice->sUsbCtlRequest.bRequestType = 0x40;
177 pDevice->sUsbCtlRequest.bRequest = byRequest;
178 pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
179 pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
180 pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
181 pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
182 pDevice->pControlURB->actual_length = 0;
183 // Notice, pbyBuffer limited point to variable buffer, can't be constant.
184 usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
185 usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
186 pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice);
187
188 ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
189 if (ntStatus != 0) {
190 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
191 "control send request submission failed: %d\n",
192 ntStatus);
193 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
194 return STATUS_FAILURE;
195 }
196
197 spin_unlock_irq(&pDevice->lock);
198 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
199
200 if (pDevice->Flags & fMP_CONTROL_WRITES)
201 mdelay(1);
202 else
203 break;
204
205 if (ii >= USB_CTL_WAIT) {
206 DBG_PRT(MSG_LEVEL_DEBUG,
207 KERN_INFO "control send request submission timeout\n");
208 spin_lock_irq(&pDevice->lock);
209 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
210 return STATUS_FAILURE;
211 }
212 }
213 spin_lock_irq(&pDevice->lock);
214
215 return STATUS_SUCCESS;
216 }
217
PIPEnsControlIn(PSDevice pDevice,BYTE byRequest,WORD wValue,WORD wIndex,WORD wLength,PBYTE pbyBuffer)218 int PIPEnsControlIn(
219 PSDevice pDevice,
220 BYTE byRequest,
221 WORD wValue,
222 WORD wIndex,
223 WORD wLength,
224 PBYTE pbyBuffer
225 )
226 {
227 int ntStatus = 0;
228 int ii;
229
230 if (pDevice->Flags & fMP_DISCONNECTED)
231 return STATUS_FAILURE;
232
233 if (pDevice->Flags & fMP_CONTROL_READS)
234 return STATUS_FAILURE;
235
236 if (pDevice->Flags & fMP_CONTROL_WRITES)
237 return STATUS_FAILURE;
238
239 MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
240
241 pDevice->sUsbCtlRequest.bRequestType = 0xC0;
242 pDevice->sUsbCtlRequest.bRequest = byRequest;
243 pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
244 pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
245 pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
246 pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
247 pDevice->pControlURB->actual_length = 0;
248 usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
249 usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
250 pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
251
252 ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
253 if (ntStatus != 0) {
254 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
255 "control request submission failed: %d\n", ntStatus);
256 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
257 return STATUS_FAILURE;
258 }
259
260 spin_unlock_irq(&pDevice->lock);
261 for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
262
263 if (pDevice->Flags & fMP_CONTROL_READS)
264 mdelay(1);
265 else
266 break;
267
268 if (ii >= USB_CTL_WAIT) {
269 DBG_PRT(MSG_LEVEL_DEBUG,
270 KERN_INFO "control rcv request submission timeout\n");
271 spin_lock_irq(&pDevice->lock);
272 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
273 return STATUS_FAILURE;
274 }
275 }
276 spin_lock_irq(&pDevice->lock);
277
278 return ntStatus;
279 }
280
281 static
282 void
s_nsControlInUsbIoCompleteWrite(struct urb * urb)283 s_nsControlInUsbIoCompleteWrite(
284 struct urb *urb
285 )
286 {
287 PSDevice pDevice;
288
289 pDevice = urb->context;
290 switch (urb->status) {
291 case 0:
292 break;
293 case -EINPROGRESS:
294 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
295 break;
296 case -ENOENT:
297 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
298 break;
299 default:
300 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
301 }
302
303 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
304 }
305
306
307
308 /*
309 * Description:
310 * Complete function of usb Control callback
311 *
312 * Parameters:
313 * In:
314 * pDevice - Pointer to the adapter
315 *
316 * Out:
317 * none
318 *
319 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
320 *
321 */
322 static
323 void
s_nsControlInUsbIoCompleteRead(struct urb * urb)324 s_nsControlInUsbIoCompleteRead(
325 struct urb *urb
326 )
327 {
328 PSDevice pDevice;
329
330 pDevice = urb->context;
331 switch (urb->status) {
332 case 0:
333 break;
334 case -EINPROGRESS:
335 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
336 break;
337 case -ENOENT:
338 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
339 break;
340 default:
341 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
342 }
343
344 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
345 }
346
347
348
349
350 /*
351 * Description:
352 * Allocates an usb interrupt in irp and calls USBD.
353 *
354 * Parameters:
355 * In:
356 * pDevice - Pointer to the adapter
357 * Out:
358 * none
359 *
360 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
361 *
362 */
PIPEnsInterruptRead(PSDevice pDevice)363 int PIPEnsInterruptRead(PSDevice pDevice)
364 {
365 int ntStatus = STATUS_FAILURE;
366
367 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartInterruptUsbRead()\n");
368
369 if(pDevice->intBuf.bInUse == TRUE){
370 return (STATUS_FAILURE);
371 }
372 pDevice->intBuf.bInUse = TRUE;
373 // pDevice->bEventAvailable = FALSE;
374 pDevice->ulIntInPosted++;
375
376 //
377 // Now that we have created the urb, we will send a
378 // request to the USB device object.
379 //
380 pDevice->pInterruptURB->interval = pDevice->int_interval;
381
382 usb_fill_bulk_urb(pDevice->pInterruptURB,
383 pDevice->usb,
384 usb_rcvbulkpipe(pDevice->usb, 1),
385 (void *) pDevice->intBuf.pDataBuf,
386 MAX_INTERRUPT_SIZE,
387 s_nsInterruptUsbIoCompleteRead,
388 pDevice);
389
390 ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
391 if (ntStatus != 0) {
392 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
393 }
394
395 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----s_nsStartInterruptUsbRead Return(%x)\n",ntStatus);
396 return ntStatus;
397 }
398
399
400 /*
401 * Description:
402 * Complete function of usb interrupt in irp.
403 *
404 * Parameters:
405 * In:
406 * pDevice - Pointer to the adapter
407 *
408 * Out:
409 * none
410 *
411 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
412 *
413 */
414 static
415 void
s_nsInterruptUsbIoCompleteRead(struct urb * urb)416 s_nsInterruptUsbIoCompleteRead(
417 struct urb *urb
418 )
419
420 {
421 PSDevice pDevice;
422 int ntStatus;
423
424 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptUsbIoCompleteRead\n");
425 //
426 // The context given to IoSetCompletionRoutine is the receive buffer object
427 //
428 pDevice = (PSDevice)urb->context;
429
430 //
431 // We have a number of cases:
432 // 1) The USB read timed out and we received no data.
433 // 2) The USB read timed out and we received some data.
434 // 3) The USB read was successful and fully filled our irp buffer.
435 // 4) The irp was cancelled.
436 // 5) Some other failure from the USB device object.
437 //
438 ntStatus = urb->status;
439
440 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsInterruptUsbIoCompleteRead Status %d\n", ntStatus);
441
442 // if we were not successful, we need to free the int buffer for future use right here
443 // otherwise interrupt data handler will free int buffer after it handle it.
444 if (( ntStatus != STATUS_SUCCESS )) {
445 pDevice->ulBulkInError++;
446 pDevice->intBuf.bInUse = FALSE;
447
448 // if (ntStatus == USBD_STATUS_CRC) {
449 // pDevice->ulIntInContCRCError++;
450 // }
451
452 // if (ntStatus == STATUS_NOT_CONNECTED )
453 // {
454 pDevice->fKillEventPollingThread = TRUE;
455 // }
456 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"IntUSBIoCompleteControl STATUS = %d\n", ntStatus );
457 } else {
458 pDevice->ulIntInBytesRead += (unsigned long) urb->actual_length;
459 pDevice->ulIntInContCRCError = 0;
460 pDevice->bEventAvailable = TRUE;
461 INTnsProcessData(pDevice);
462 }
463
464 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_InterruptStat, ntStatus);
465
466
467 if (pDevice->fKillEventPollingThread != TRUE) {
468 usb_fill_bulk_urb(pDevice->pInterruptURB,
469 pDevice->usb,
470 usb_rcvbulkpipe(pDevice->usb, 1),
471 (void *) pDevice->intBuf.pDataBuf,
472 MAX_INTERRUPT_SIZE,
473 s_nsInterruptUsbIoCompleteRead,
474 pDevice);
475
476 ntStatus = usb_submit_urb(pDevice->pInterruptURB, GFP_ATOMIC);
477 if (ntStatus != 0) {
478 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit int URB failed %d\n", ntStatus);
479 }
480 }
481 //
482 // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
483 // routine (IofCompleteRequest) will stop working on the irp.
484 //
485 return ;
486 }
487
488 /*
489 * Description:
490 * Allocates an usb BulkIn irp and calls USBD.
491 *
492 * Parameters:
493 * In:
494 * pDevice - Pointer to the adapter
495 * Out:
496 * none
497 *
498 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
499 *
500 */
PIPEnsBulkInUsbRead(PSDevice pDevice,PRCB pRCB)501 int PIPEnsBulkInUsbRead(PSDevice pDevice, PRCB pRCB)
502 {
503 int ntStatus = 0;
504 struct urb *pUrb;
505
506
507 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
508
509 if (pDevice->Flags & fMP_DISCONNECTED)
510 return STATUS_FAILURE;
511
512 pDevice->ulBulkInPosted++;
513
514
515 pUrb = pRCB->pUrb;
516 //
517 // Now that we have created the urb, we will send a
518 // request to the USB device object.
519 //
520 if (pRCB->skb == NULL) {
521 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pRCB->skb is null \n");
522 return ntStatus;
523 }
524
525 usb_fill_bulk_urb(pUrb,
526 pDevice->usb,
527 usb_rcvbulkpipe(pDevice->usb, 2),
528 (void *) (pRCB->skb->data),
529 MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
530 s_nsBulkInUsbIoCompleteRead,
531 pRCB);
532
533 ntStatus = usb_submit_urb(pUrb, GFP_ATOMIC);
534 if (ntStatus != 0) {
535 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Rx URB failed %d\n", ntStatus);
536 return STATUS_FAILURE ;
537 }
538 pRCB->Ref = 1;
539 pRCB->bBoolInUse= TRUE;
540
541 return ntStatus;
542 }
543
544
545
546
547 /*
548 * Description:
549 * Complete function of usb BulkIn irp.
550 *
551 * Parameters:
552 * In:
553 * pDevice - Pointer to the adapter
554 *
555 * Out:
556 * none
557 *
558 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
559 *
560 */
561 static
562 void
s_nsBulkInUsbIoCompleteRead(struct urb * urb)563 s_nsBulkInUsbIoCompleteRead(
564 struct urb *urb
565 )
566
567 {
568 PRCB pRCB = (PRCB)urb->context;
569 PSDevice pDevice = (PSDevice)pRCB->pDevice;
570 unsigned long bytesRead;
571 BOOL bIndicateReceive = FALSE;
572 BOOL bReAllocSkb = FALSE;
573 int status;
574
575 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
576 status = urb->status;
577 bytesRead = urb->actual_length;
578
579 if (status) {
580 pDevice->ulBulkInError++;
581 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK In failed %d\n", status);
582
583 pDevice->scStatistic.RxFcsErrCnt ++;
584 //todo...xxxxxx
585 // if (status == USBD_STATUS_CRC) {
586 // pDevice->ulBulkInContCRCError++;
587 // }
588 // if (status == STATUS_DEVICE_NOT_CONNECTED )
589 // {
590 // MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
591 // }
592 } else {
593 bIndicateReceive = TRUE;
594 pDevice->ulBulkInContCRCError = 0;
595 pDevice->ulBulkInBytesRead += bytesRead;
596
597 pDevice->scStatistic.RxOkCnt ++;
598 }
599
600
601 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkInStat, status);
602
603 if (bIndicateReceive) {
604 spin_lock(&pDevice->lock);
605 if (RXbBulkInProcessData(pDevice, pRCB, bytesRead) == TRUE)
606 bReAllocSkb = TRUE;
607 spin_unlock(&pDevice->lock);
608 }
609 pRCB->Ref--;
610 if (pRCB->Ref == 0)
611 {
612 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d \n",pDevice->NumRecvFreeList);
613 spin_lock(&pDevice->lock);
614 RXvFreeRCB(pRCB, bReAllocSkb);
615 spin_unlock(&pDevice->lock);
616 }
617
618
619 return;
620 }
621
622 /*
623 * Description:
624 * Allocates an usb BulkOut irp and calls USBD.
625 *
626 * Parameters:
627 * In:
628 * pDevice - Pointer to the adapter
629 * Out:
630 * none
631 *
632 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
633 *
634 */
635 int
PIPEnsSendBulkOut(PSDevice pDevice,PUSB_SEND_CONTEXT pContext)636 PIPEnsSendBulkOut(
637 PSDevice pDevice,
638 PUSB_SEND_CONTEXT pContext
639 )
640 {
641 int status;
642 struct urb *pUrb;
643
644
645
646 pDevice->bPWBitOn = FALSE;
647
648 /*
649 if (pDevice->pPendingBulkOutContext != NULL) {
650 pDevice->NumContextsQueued++;
651 EnqueueContext(pDevice->FirstTxContextQueue, pDevice->LastTxContextQueue, pContext);
652 status = STATUS_PENDING;
653 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send pending!\n");
654 return status;
655 }
656 */
657
658 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
659
660 if (MP_IS_READY(pDevice) && (pDevice->Flags & fMP_POST_WRITES)) {
661
662 pUrb = pContext->pUrb;
663 pDevice->ulBulkOutPosted++;
664 // pDevice->pPendingBulkOutContext = pContext;
665 usb_fill_bulk_urb(
666 pUrb,
667 pDevice->usb,
668 usb_sndbulkpipe(pDevice->usb, 3),
669 (void *) &(pContext->Data[0]),
670 pContext->uBufLen,
671 s_nsBulkOutIoCompleteWrite,
672 pContext);
673
674 status = usb_submit_urb(pUrb, GFP_ATOMIC);
675 if (status != 0)
676 {
677 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Submit Tx URB failed %d\n", status);
678 return STATUS_FAILURE;
679 }
680 return STATUS_PENDING;
681 }
682 else {
683 pContext->bBoolInUse = FALSE;
684 return STATUS_RESOURCES;
685 }
686 }
687
688 /*
689 * Description: s_nsBulkOutIoCompleteWrite
690 * 1a) Indicate to the protocol the status of the write.
691 * 1b) Return ownership of the packet to the protocol.
692 *
693 * 2) If any more packets are queue for sending, send another packet
694 * to USBD.
695 * If the attempt to send the packet to the driver fails,
696 * return ownership of the packet to the protocol and
697 * try another packet (until one succeeds).
698 *
699 * Parameters:
700 * In:
701 * pdoUsbDevObj - pointer to the USB device object which
702 * completed the irp
703 * pIrp - the irp which was completed by the
704 * device object
705 * pContext - the context given to IoSetCompletionRoutine
706 * before calling IoCallDriver on the irp
707 * The pContext is a pointer to the USB device object.
708 * Out:
709 * none
710 *
711 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
712 * (IofCompleteRequest) to stop working on the irp.
713 *
714 */
715 static
716 void
s_nsBulkOutIoCompleteWrite(struct urb * urb)717 s_nsBulkOutIoCompleteWrite(
718 struct urb *urb
719 )
720 {
721 PSDevice pDevice;
722 int status;
723 CONTEXT_TYPE ContextType;
724 unsigned long ulBufLen;
725 PUSB_SEND_CONTEXT pContext;
726
727
728 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
729 //
730 // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
731 //
732 pContext = (PUSB_SEND_CONTEXT) urb->context;
733 ASSERT( NULL != pContext );
734
735 pDevice = pContext->pDevice;
736 ContextType = pContext->Type;
737 ulBufLen = pContext->uBufLen;
738
739 if (!netif_device_present(pDevice->dev))
740 return;
741
742 //
743 // Perform various IRP, URB, and buffer 'sanity checks'
744 //
745
746 status = urb->status;
747 //we should have failed, succeeded, or cancelled, but NOT be pending
748 STAvUpdateUSBCounter(&pDevice->scStatistic.USB_BulkOutStat, status);
749
750 if(status == STATUS_SUCCESS) {
751 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
752 pDevice->ulBulkOutBytesWrite += ulBufLen;
753 pDevice->ulBulkOutContCRCError = 0;
754 pDevice->nTxDataTimeCout = 0;
755
756 } else {
757 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
758 pDevice->ulBulkOutError++;
759 }
760
761 // pDevice->ulCheckForHangCount = 0;
762 // pDevice->pPendingBulkOutContext = NULL;
763
764 if ( CONTEXT_DATA_PACKET == ContextType ) {
765 // Indicate to the protocol the status of the sent packet and return
766 // ownership of the packet.
767 if (pContext->pPacket != NULL) {
768 dev_kfree_skb_irq(pContext->pPacket);
769 pContext->pPacket = NULL;
770 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"tx %d bytes\n",(int)ulBufLen);
771 }
772
773 pDevice->dev->trans_start = jiffies;
774
775
776 if (status == STATUS_SUCCESS) {
777 pDevice->packetsSent++;
778 }
779 else {
780 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Send USB error! [%08xh]\n", status);
781 pDevice->packetsSentDropped++;
782 }
783
784 }
785 if (pDevice->bLinkPass == TRUE) {
786 if (netif_queue_stopped(pDevice->dev))
787 netif_wake_queue(pDevice->dev);
788 }
789 pContext->bBoolInUse = FALSE;
790
791 return;
792 }
793