Linux Audio

Check our new training course

Loading...
v3.15
  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//endpoint def
 49//endpoint 0: control
 50//endpoint 1: interrupt
 51//endpoint 2: read bulk
 52//endpoint 3: write bulk
 53
 
 
 
 54//static int          msglevel                =MSG_LEVEL_DEBUG;
 55static int          msglevel                =MSG_LEVEL_INFO;
 56
 
 57#define USB_CTL_WAIT   500 //ms
 58
 59#ifndef URB_ASYNC_UNLINK
 60#define URB_ASYNC_UNLINK    0
 61#endif
 62
 63static void s_nsInterruptUsbIoCompleteRead(struct urb *urb);
 64static void s_nsBulkInUsbIoCompleteRead(struct urb *urb);
 65static void s_nsBulkOutIoCompleteWrite(struct urb *urb);
 66static void s_nsControlInUsbIoCompleteRead(struct urb *urb);
 67static void s_nsControlInUsbIoCompleteWrite(struct urb *urb);
 68
 69int PIPEnsControlOutAsyn(struct vnt_private *pDevice, u8 byRequest,
 70	u16 wValue, u16 wIndex, u16 wLength, u8 *pbyBuffer)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 71{
 72	int ntStatus;
 73
 74    if (pDevice->Flags & fMP_DISCONNECTED)
 75        return STATUS_FAILURE;
 76
 77    if (pDevice->Flags & fMP_CONTROL_WRITES)
 78        return STATUS_FAILURE;
 79
 80    if (in_interrupt()) {
 81        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"in_interrupt return ..byRequest %x\n", byRequest);
 82        return STATUS_FAILURE;
 83    }
 84
 85    ntStatus = usb_control_msg(
 86                            pDevice->usb,
 87                            usb_sndctrlpipe(pDevice->usb , 0),
 88                            byRequest,
 89                            0x40, // RequestType
 90                            wValue,
 91                            wIndex,
 92			    (void *) pbyBuffer,
 93                            wLength,
 94                            HZ
 95                          );
 96    if (ntStatus >= 0) {
 97        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe ntStatus= %d\n", ntStatus);
 98        ntStatus = 0;
 99    } else {
100        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"usb_sndctrlpipe fail, ntStatus= %d\n", ntStatus);
101    }
102
103    return ntStatus;
104}
105
106int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
107		u16 wIndex, u16 wLength, u8 *pbyBuffer)
108		__releases(&pDevice->lock)
109		__acquires(&pDevice->lock)
 
 
 
 
110{
111	int ntStatus = 0;
112	int ii;
113
114    if (pDevice->Flags & fMP_DISCONNECTED)
115        return STATUS_FAILURE;
116
117    if (pDevice->Flags & fMP_CONTROL_WRITES)
118        return STATUS_FAILURE;
119
120	if (pDevice->Flags & fMP_CONTROL_READS)
121		return STATUS_FAILURE;
122
123	if (pDevice->pControlURB->hcpriv)
124		return STATUS_FAILURE;
125
126	MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
127
128	pDevice->sUsbCtlRequest.bRequestType = 0x40;
129	pDevice->sUsbCtlRequest.bRequest = byRequest;
130	pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
131	pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
132	pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
133	pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
134    pDevice->pControlURB->actual_length = 0;
135    // Notice, pbyBuffer limited point to variable buffer, can't be constant.
136  	usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
137			 usb_sndctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
138			 pbyBuffer, wLength, s_nsControlInUsbIoCompleteWrite, pDevice);
139
140	ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
141	if (ntStatus != 0) {
142		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
143			"control send request submission failed: %d\n",
144				ntStatus);
145		MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
146		return STATUS_FAILURE;
147	}
148
 
 
149	spin_unlock_irq(&pDevice->lock);
150    for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
151
152	if (pDevice->Flags & fMP_CONTROL_WRITES)
153		mdelay(1);
154        else
155		break;
156
157        if (ii >= USB_CTL_WAIT) {
158		DBG_PRT(MSG_LEVEL_DEBUG,
159			KERN_INFO "control send request submission timeout\n");
160            spin_lock_irq(&pDevice->lock);
161            MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
162            return STATUS_FAILURE;
163        }
164    }
165	spin_lock_irq(&pDevice->lock);
166
167    return STATUS_SUCCESS;
168}
169
170int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue,
171	u16 wIndex, u16 wLength,  u8 *pbyBuffer)
172	__releases(&pDevice->lock)
173	__acquires(&pDevice->lock)
 
 
 
 
174{
175	int ntStatus = 0;
176	int ii;
177
178    if (pDevice->Flags & fMP_DISCONNECTED)
179        return STATUS_FAILURE;
180
181    if (pDevice->Flags & fMP_CONTROL_READS)
182	return STATUS_FAILURE;
183
184	if (pDevice->Flags & fMP_CONTROL_WRITES)
185		return STATUS_FAILURE;
186
187	if (pDevice->pControlURB->hcpriv)
188		return STATUS_FAILURE;
189
190	MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
191
192	pDevice->sUsbCtlRequest.bRequestType = 0xC0;
193	pDevice->sUsbCtlRequest.bRequest = byRequest;
194	pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue);
195	pDevice->sUsbCtlRequest.wIndex = cpu_to_le16p(&wIndex);
196	pDevice->sUsbCtlRequest.wLength = cpu_to_le16p(&wLength);
197	pDevice->pControlURB->transfer_flags |= URB_ASYNC_UNLINK;
198    pDevice->pControlURB->actual_length = 0;
199	usb_fill_control_urb(pDevice->pControlURB, pDevice->usb,
200			 usb_rcvctrlpipe(pDevice->usb , 0), (char *) &pDevice->sUsbCtlRequest,
201			 pbyBuffer, wLength, s_nsControlInUsbIoCompleteRead, pDevice);
202
203	ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC);
204	if (ntStatus != 0) {
205		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
206			"control request submission failed: %d\n", ntStatus);
207		MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
208		return STATUS_FAILURE;
209	}
210
211	spin_unlock_irq(&pDevice->lock);
212    for (ii = 0; ii <= USB_CTL_WAIT; ii ++) {
213
214	if (pDevice->Flags & fMP_CONTROL_READS)
215		mdelay(1);
216	else
217		break;
218
219	if (ii >= USB_CTL_WAIT) {
220		DBG_PRT(MSG_LEVEL_DEBUG,
221			KERN_INFO "control rcv request submission timeout\n");
222            spin_lock_irq(&pDevice->lock);
223            MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
224            return STATUS_FAILURE;
225        }
226    }
227	spin_lock_irq(&pDevice->lock);
228
229    return ntStatus;
230}
231
232static void s_nsControlInUsbIoCompleteWrite(struct urb *urb)
 
 
 
 
233{
234	struct vnt_private *pDevice = (struct vnt_private *)urb->context;
235
236	pDevice = urb->context;
237	switch (urb->status) {
238	case 0:
239		break;
240	case -EINPROGRESS:
241		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status EINPROGRESS%d\n", urb->status);
242		break;
243	case -ENOENT:
244		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status ENOENT %d\n", urb->status);
245		break;
246	default:
247		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl write urb status %d\n", urb->status);
248	}
249
250    MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
251}
252
 
 
253/*
254 * Description:
255 *      Complete function of usb Control callback
256 *
257 * Parameters:
258 *  In:
259 *      pDevice     - Pointer to the adapter
260 *
261 *  Out:
262 *      none
263 *
264 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
265 *
266 */
267
268static void s_nsControlInUsbIoCompleteRead(struct urb *urb)
 
 
 
269{
270	struct vnt_private *pDevice = (struct vnt_private *)urb->context;
271
 
272	switch (urb->status) {
273	case 0:
274		break;
275	case -EINPROGRESS:
276		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status EINPROGRESS%d\n", urb->status);
277		break;
278	case -ENOENT:
279		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status = ENOENT %d\n", urb->status);
280		break;
281	default:
282		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ctrl read urb status %d\n", urb->status);
283	}
284
285    MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
286}
287
 
 
 
288/*
289 * Description:
290 *      Allocates an usb interrupt in irp and calls USBD.
291 *
292 * Parameters:
293 *  In:
294 *      pDevice     - Pointer to the adapter
295 *  Out:
296 *      none
297 *
298 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
299 *
300 */
301
302int PIPEnsInterruptRead(struct vnt_private *priv)
303{
304	int status = STATUS_FAILURE;
305
306	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
307			"---->s_nsStartInterruptUsbRead()\n");
308
309	if (priv->int_buf.in_use == true)
310		return STATUS_FAILURE;
311
312	priv->int_buf.in_use = true;
313
314	usb_fill_int_urb(priv->pInterruptURB,
315		priv->usb,
316		usb_rcvintpipe(priv->usb, 1),
317		priv->int_buf.data_buf,
 
 
 
 
 
 
 
 
 
 
 
 
 
318		MAX_INTERRUPT_SIZE,
319		s_nsInterruptUsbIoCompleteRead,
320		priv,
321		priv->int_interval);
322
323	status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
324	if (status) {
325		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
326			"Submit int URB failed %d\n", status);
327		priv->int_buf.in_use = false;
328	}
329
330	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
331		"<----s_nsStartInterruptUsbRead Return(%x)\n", status);
 
 
332
333	return status;
 
334}
335
 
336/*
337 * Description:
338 *      Complete function of usb interrupt in irp.
339 *
340 * Parameters:
341 *  In:
342 *      pDevice     - Pointer to the adapter
343 *
344 *  Out:
345 *      none
346 *
347 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
348 *
349 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
351static void s_nsInterruptUsbIoCompleteRead(struct urb *urb)
352{
353	struct vnt_private *priv = urb->context;
354	int status;
355
356	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
357			"---->s_nsInterruptUsbIoCompleteRead\n");
358
359	switch (urb->status) {
360	case 0:
361	case -ETIMEDOUT:
362		break;
363	case -ECONNRESET:
364	case -ENOENT:
365	case -ESHUTDOWN:
366		priv->int_buf.in_use = false;
367		return;
368	default:
369		break;
370	}
371
372	status = urb->status;
373
374	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
375		"s_nsInterruptUsbIoCompleteRead Status %d\n", status);
376
377	if (status != STATUS_SUCCESS) {
378		priv->int_buf.in_use = false;
379
380		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
381			"IntUSBIoCompleteControl STATUS = %d\n", status);
382	} else {
383		INTnsProcessData(priv);
384	}
385
386	status = usb_submit_urb(priv->pInterruptURB, GFP_ATOMIC);
387	if (status) {
388		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
389			"Submit int URB failed %d\n", status);
390	} else {
391		priv->int_buf.in_use = true;
392	}
 
393
394	return;
 
 
 
 
 
 
 
 
 
395}
396
397/*
398 * Description:
399 *      Allocates an usb BulkIn  irp and calls USBD.
400 *
401 * Parameters:
402 *  In:
403 *      pDevice     - Pointer to the adapter
404 *  Out:
405 *      none
406 *
407 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
408 *
409 */
410
411int PIPEnsBulkInUsbRead(struct vnt_private *priv, struct vnt_rcb *rcb)
412{
413	int status = 0;
414	struct urb *urb;
415
416	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsStartBulkInUsbRead\n");
417
418	if (priv->Flags & fMP_DISCONNECTED)
419		return STATUS_FAILURE;
420
421	urb = rcb->pUrb;
422	if (rcb->skb == NULL) {
423		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rcb->skb is null\n");
424		return status;
425	}
 
 
 
 
 
 
 
 
 
 
426
427	usb_fill_bulk_urb(urb,
428		priv->usb,
429		usb_rcvbulkpipe(priv->usb, 2),
430		(void *) (rcb->skb->data),
431		MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
432		s_nsBulkInUsbIoCompleteRead,
433		rcb);
434
435	status = usb_submit_urb(urb, GFP_ATOMIC);
436	if (status != 0) {
437		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
438				"Submit Rx URB failed %d\n", status);
439		return STATUS_FAILURE ;
440	}
 
 
441
442	rcb->Ref = 1;
443	rcb->bBoolInUse = true;
444
445	return status;
446}
447
 
 
 
448/*
449 * Description:
450 *      Complete function of usb BulkIn irp.
451 *
452 * Parameters:
453 *  In:
454 *      pDevice     - Pointer to the adapter
455 *
456 *  Out:
457 *      none
458 *
459 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
460 *
461 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
463static void s_nsBulkInUsbIoCompleteRead(struct urb *urb)
464{
465	struct vnt_rcb *rcb = urb->context;
466	struct vnt_private *priv = rcb->pDevice;
467	int re_alloc_skb = false;
468
469	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkInUsbIoCompleteRead\n");
470
471	switch (urb->status) {
472	case 0:
473		break;
474	case -ECONNRESET:
475	case -ENOENT:
476	case -ESHUTDOWN:
477		return;
478	case -ETIMEDOUT:
479	default:
480		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
481				"BULK In failed %d\n", urb->status);
482		break;
483	}
484
485	if (urb->actual_length) {
486		spin_lock(&priv->lock);
487
488		if (RXbBulkInProcessData(priv, rcb, urb->actual_length) == true)
489			re_alloc_skb = true;
490
491		spin_unlock(&priv->lock);
492	}
493
494	rcb->Ref--;
495	if (rcb->Ref == 0) {
496		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"RxvFreeNormal %d\n",
497							priv->NumRecvFreeList);
498		spin_lock(&priv->lock);
499
500		RXvFreeRCB(rcb, re_alloc_skb);
 
 
 
 
 
 
 
 
 
 
 
 
 
501
502		spin_unlock(&priv->lock);
503	}
504
505	return;
506}
507
508/*
509 * Description:
510 *      Allocates an usb BulkOut  irp and calls USBD.
511 *
512 * Parameters:
513 *  In:
514 *      pDevice     - Pointer to the adapter
515 *  Out:
516 *      none
517 *
518 * Return Value: STATUS_INSUFFICIENT_RESOURCES or result of IoCallDriver
519 *
520 */
521
522int PIPEnsSendBulkOut(struct vnt_private *priv,
523				struct vnt_usb_send_context *context)
 
 
524{
525	int status;
526	struct urb *urb;
527
528	priv->bPWBitOn = false;
529
530	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_nsSendBulkOut\n");
531
532	if (!(MP_IS_READY(priv) && priv->Flags & fMP_POST_WRITES)) {
533		context->bBoolInUse = false;
534		return STATUS_RESOURCES;
535	}
536
537	urb = context->pUrb;
 
 
 
 
 
 
 
 
538
539	usb_fill_bulk_urb(urb,
540			priv->usb,
541			usb_sndbulkpipe(priv->usb, 3),
542			context->Data,
543			context->uBufLen,
544			s_nsBulkOutIoCompleteWrite,
545			context);
546
547	status = usb_submit_urb(urb, GFP_ATOMIC);
548	if (status != 0) {
549		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
550				"Submit Tx URB failed %d\n", status);
551		context->bBoolInUse = false;
552		return STATUS_FAILURE;
553	}
554
555	return STATUS_PENDING;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556}
557
558/*
559 * Description: s_nsBulkOutIoCompleteWrite
560 *     1a) Indicate to the protocol the status of the write.
561 *     1b) Return ownership of the packet to the protocol.
562 *
563 *     2)  If any more packets are queue for sending, send another packet
564 *         to USBD.
565 *         If the attempt to send the packet to the driver fails,
566 *         return ownership of the packet to the protocol and
567 *         try another packet (until one succeeds).
568 *
569 * Parameters:
570 *  In:
571 *      pdoUsbDevObj  - pointer to the USB device object which
572 *                      completed the irp
573 *      pIrp          - the irp which was completed by the
574 *                      device object
575 *      pContext      - the context given to IoSetCompletionRoutine
576 *                      before calling IoCallDriver on the irp
577 *                      The pContext is a pointer to the USB device object.
578 *  Out:
579 *      none
580 *
581 * Return Value: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
582 *               (IofCompleteRequest) to stop working on the irp.
583 *
584 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
585
586static void s_nsBulkOutIoCompleteWrite(struct urb *urb)
587{
588	struct vnt_usb_send_context *context = urb->context;
589	struct vnt_private *priv = context->pDevice;
590	u8 context_type = context->type;
591
592	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsBulkOutIoCompleteWrite\n");
593
594	switch (urb->status) {
595	case 0:
596		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
597			"Write %d bytes\n", context->uBufLen);
598		break;
599	case -ECONNRESET:
600	case -ENOENT:
601	case -ESHUTDOWN:
602		context->bBoolInUse = false;
603		return;
604	case -ETIMEDOUT:
605	default:
606		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
607				"BULK Out failed %d\n", urb->status);
608		break;
609	}
610
611	if (!netif_device_present(priv->dev))
612		return;
 
 
 
 
 
 
613
614	if (CONTEXT_DATA_PACKET == context_type) {
615		if (context->pPacket != NULL) {
616			dev_kfree_skb_irq(context->pPacket);
617			context->pPacket = NULL;
618			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO
619				"tx  %d bytes\n", context->uBufLen);
620		}
621
622		priv->dev->trans_start = jiffies;
623	}
624
625	if (priv->bLinkPass == true) {
626		if (netif_queue_stopped(priv->dev))
627			netif_wake_queue(priv->dev);
628	}
 
 
 
629
630	context->bBoolInUse = false;
 
 
 
 
 
631
632	return;
633}
v3.5.6
  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;
 59static 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  --------------------------*/
 73static
 74void
 75s_nsInterruptUsbIoCompleteRead(
 76     struct urb *urb
 77    );
 78
 79
 80static
 81void
 82s_nsBulkInUsbIoCompleteRead(
 83     struct urb *urb
 84    );
 85
 86
 87static
 88void
 89s_nsBulkOutIoCompleteWrite(
 90     struct urb *urb
 91    );
 92
 93
 94static
 95void
 96s_nsControlInUsbIoCompleteRead(
 97     struct urb *urb
 98    );
 99
100static
101void
102s_nsControlInUsbIoCompleteWrite(
103     struct urb *urb
104    );
105
106/*---------------------  Export Variables  --------------------------*/
107
108/*---------------------  Export Functions  --------------------------*/
109
110int 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
153int 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
212int 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
269static
270void
271s_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 */
310static
311void
312s_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 */
351int 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
370usb_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 */
402static
403void
404s_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 */
489int 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 */
549static
550void
551s_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 */
623int
624PIPEnsSendBulkOut(
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 */
703static
704void
705s_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}