2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*****************************************************************************
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Filename :       irda - usb . c 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Version :        0.10 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *  Description :    IrDA - USB  Driver 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Status :         Experimental  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Author :         Dag  Brattli  < dag @ brattli . net > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	Copyright  ( C )  2000 ,  Roman  Weissgaerber  < weissg @ vienna . at > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *       Copyright  ( C )  2001 ,  Dag  Brattli  < dag @ brattli . net > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *       Copyright  ( C )  2001 ,  Jean  Tourrilhes  < jt @ hpl . hp . com > 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *       Copyright  ( C )  2004 ,  SigmaTel ,  Inc .  < irquality @ sigmatel . com > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *       Copyright  ( C )  2005 ,  Milan  Beno  < beno @ pobox . sk > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *       Copyright  ( C )  2006 ,  Nick  Fedchik  < nick @ fedchik . org . ua > 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 *           
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	This  program  is  free  software ;  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	it  under  the  terms  of  the  GNU  General  Public  License  as  published  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	the  Free  Software  Foundation ;  either  version  2  of  the  License ,  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	This  program  is  distributed  in  the  hope  that  it  will  be  useful , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	GNU  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	You  should  have  received  a  copy  of  the  GNU  General  Public  License 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	along  with  this  program ;  if  not ,  write  to  the  Free  Software 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	Foundation ,  Inc . ,  675  Mass  Ave ,  Cambridge ,  MA  0213 9 ,  USA . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 			    IMPORTANT  NOTE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 			    - - - - - - - - - - - - - - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  As  of  kernel  2.5 .20 ,  this  is  the  state  of  compliance  and  testing  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  this  driver  ( irda - usb )  with  regards  to  the  USB  low  level  drivers . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  driver  has  been  tested  SUCCESSFULLY  with  the  following  drivers  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	o  usb - uhci - hcd 	( For  Intel / Via  USB  controllers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	o  uhci - hcd 	( Alternate / JE  driver  for  Intel / Via  USB  controllers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	o  ohci - hcd 	( For  other  USB  controllers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  driver  has  NOT  been  tested  with  the  following  drivers  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 	o  ehci - hcd 	( USB  2.0  controllers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  that  all  HCD  drivers  do  URB_ZERO_PACKET  and  timeout  properly , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  so  we  don ' t  have  to  worry  about  that  anymore . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  One  common  problem  is  the  failure  to  set  the  address  on  the  dongle , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  but  this  happens  before  the  driver  gets  loaded . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/module.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/moduleparam.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/kernel.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/types.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/init.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/skbuff.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/netdevice.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/slab.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/rtnetlink.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/usb.h> 
  
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <linux/firmware.h> 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  "irda-usb.h" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  qos_mtt_bits  =  0 ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* These are the currently known IrDA USB dongles. Add new dongles here */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  usb_device_id  dongles [ ]  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* ACTiSYS Corp.,  ACT-IR2000U FIR-USB Adapter */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x9c4 ,  0x011 ) ,  . driver_info  =  IUC_SPEED_BUG  |  IUC_NO_WINDOW  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Look like ACTiSYS, Report : IBM Corp., IBM UltraPort IrDA */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x4428 ,  0x012 ) ,  . driver_info  =  IUC_SPEED_BUG  |  IUC_NO_WINDOW  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* KC Technology Inc.,  KC-180 USB IrDA Device */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x50f ,  0x180 ) ,  . driver_info  =  IUC_SPEED_BUG  |  IUC_NO_WINDOW  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x8e9 ,  0x100 ) ,  . driver_info  =  IUC_SPEED_BUG  |  IUC_NO_WINDOW  } , 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x66f ,  0x4210 ) ,  . driver_info  =  IUC_STIR421X  |  IUC_SPEED_BUG  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x66f ,  0x4220 ) ,  . driver_info  =  IUC_STIR421X  |  IUC_SPEED_BUG  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  USB_DEVICE ( 0x66f ,  0x4116 ) ,  . driver_info  =  IUC_STIR421X  |  IUC_SPEED_BUG  } , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									{  . match_flags  =  USB_DEVICE_ID_MATCH_INT_CLASS  | 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									  USB_DEVICE_ID_MATCH_INT_SUBCLASS , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									  . bInterfaceClass  =  USB_CLASS_APP_SPEC , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									  . bInterfaceSubClass  =  USB_CLASS_IRDA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									  . driver_info  =  IUC_DEFAULT ,  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{  } ,  /* The end */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Important  note  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Devices  based  on  the  SigmaTel  chipset  ( 0x66f ,  0x4200 )  are  not  designed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  using  the  " USB-IrDA specification "  ( yes ,  there  exist  such  a  thing ) ,  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  therefore  not  supported  by  this  driver  ( don ' t  add  them  above ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  There  is  a  Linux  driver ,  stir4200 ,  that  support  those  USB  devices . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MODULE_DEVICE_TABLE ( usb ,  dongles ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  irda_usb_init_qos ( struct  irda_usb_cb  * self )  ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  struct  irda_class_desc  * irda_usb_find_class_desc ( struct  usb_interface  * intf ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_disconnect ( struct  usb_interface  * intf ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_change_speed_xbofs ( struct  irda_usb_cb  * self ) ;  
						 
					
						
							
								
									
										
										
										
											2009-08-31 19:50:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  netdev_tx_t  irda_usb_hard_xmit ( struct  sk_buff  * skb ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    struct  net_device  * dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_open ( struct  irda_usb_cb  * self ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_close ( struct  irda_usb_cb  * self ) ;  
						 
					
						
							
								
									
										
											 
										
											
												IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around.  On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable.  On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions.  Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller.  A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs.  Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
	struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
	set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
	-	update_process_times(user_mode(regs));
	-	profile_tick(CPU_PROFILING, regs);
	+	update_process_times(user_mode(get_irq_regs()));
	+	profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
 (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
     the input_dev struct.
 (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
     something different depending on whether it's been supplied with a regs
     pointer or not.
 (*) Various IRQ handler function pointers have been moved to type
     irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
											 
										 
										
											2006-10-05 14:55:46 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  speed_bulk_callback ( struct  urb  * urb ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  write_bulk_callback ( struct  urb  * urb ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_receive ( struct  urb  * urb ) ;  
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  irda_usb_rx_defer_expired ( unsigned  long  data ) ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_open ( struct  net_device  * dev ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_close ( struct  net_device  * dev ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_ioctl ( struct  net_device  * dev ,  struct  ifreq  * rq ,  int  cmd ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_net_timeout ( struct  net_device  * dev ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/************************ TRANSMIT ROUTINES ************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Receive  packets  from  the  IrDA  stack  and  send  them  on  the  USB  pipe . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Handle  speed  change ,  timeout  and  lot ' s  of  ugliness . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_build_header ( self ,  skb ,  header ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    Builds  USB - IrDA  outbound  header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  When  we  send  an  IrDA  frame  over  an  USB  pipe ,  we  add  to  it  a  1  byte 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  header .  This  function  create  this  header  with  the  proper  values . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Important  note  :  the  USB - IrDA  spec  1.0  say  very  clearly  in  chapter  5.4 .2 .2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  that  the  setting  of  the  link  speed  and  xbof  number  in  this  outbound  header 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  should  be  applied  * AFTER *  the  frame  has  been  sent . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Unfortunately ,  some  devices  are  not  compliant  with  that . . .  It  seems  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reading  the  spec  is  far  too  difficult . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_build_header ( struct  irda_usb_cb  * self ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												  __u8  * header , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												  int 	force ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Here we check if we have an STIR421x chip,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  and  if  either  speed  or  xbofs  ( or  both )  needs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  be  changed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_STIR421X  & & 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									    ( ( self - > new_speed  ! =  - 1 )  | |  ( self - > new_xbofs  ! =  - 1 ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* With STIR421x, speed and xBOFs must be set at the same
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  time ,  even  if  only  one  of  them  changes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( self - > new_speed  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_speed  =  self - > speed  ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( self - > new_xbofs  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_xbofs  =  self - > xbofs  ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Set the link speed */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( self - > new_speed  ! =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Hum... Ugly hack :-(
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Some  device  are  not  compliant  with  the  spec  and  change 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  parameters  * before *  sending  the  frame .  -  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( self - > capability  &  IUC_SPEED_BUG )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( ! force )  & &  ( self - > speed  ! =  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* No speed and xbofs change here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  ( we ' ll  do  it  later  in  the  write  callback )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											IRDA_DEBUG ( 2 ,  " %s(), not changing speed yet \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											* header  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 2 ,  " %s(), changing speed to %d \n " ,  __func__ ,  self - > new_speed ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										self - > speed  =  self - > new_speed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We will do ` self->new_speed = -1; ' in the completion
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  handler  just  in  case  the  current  URB  fail  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( self - > speed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  2400 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_2400 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  9600 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  =  SPEED_9600 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  19200 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  =  SPEED_19200 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  38400 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  =  SPEED_38400 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  57600 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_57600 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  115200 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_115200 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  576000 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_576000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  1152000 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_1152000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  4000000 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        * header  =  SPEED_4000000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_xbofs  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  16000000 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  =  SPEED_16000000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  			self - > new_xbofs  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  			break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  		} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									}  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* No change */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* header  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Set the negotiated additional XBOFS */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > new_xbofs  ! =  - 1 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 2 ,  " %s(), changing xbofs to %d \n " ,  __func__ ,  self - > new_xbofs ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										self - > xbofs  =  self - > new_xbofs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We will do ` self->new_xbofs = -1; ' in the completion
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  handler  just  in  case  the  current  URB  fail  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( self - > xbofs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  48 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x10 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  28 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  24 : 	/* USB spec 1.0 says 24 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x20 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  12 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x30 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  5 :  /* Bug in IrLAP spec? (should be 6) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  6 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x40 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x50 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x60 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x70 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* header  | =  0x80 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*    calculate  turnaround  time  for  SigmaTel  header  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  __u8  get_turnaround_time ( struct  sk_buff  * skb )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  turnaround_time  =  irda_get_mtt ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  (  turnaround_time  = =  0  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  10  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  50  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  100  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  500  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  1000  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  (  turnaround_time  < =  5000  ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  6 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  7 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Send  a  command  to  change  the  speed  of  the  dongle 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Need  to  be  called  with  spinlock  on . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_change_speed_xbofs ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__u8  * frame ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  urb  * urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s(), speed=%d, xbofs=%d \n " ,  __func__ , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										   self - > new_speed ,  self - > new_xbofs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Grab the speed URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb  =  self - > speed_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), URB still in use! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate the fake frame */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									frame  =  self - > speed_buff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Set the new speed and xbofs in this fake frame */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_usb_build_header ( self ,  frame ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_STIR421X )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( frame [ 0 ]  = =  0 )  return  ;  // do nothing if no change
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										frame [ 1 ]  =  0 ;  // other parameters don't change here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										frame [ 2 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Submit the 0 length IrDA frame to trigger new speed settings */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        usb_fill_bulk_urb ( urb ,  self - > usbdev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      usb_sndbulkpipe ( self - > usbdev ,  self - > bulk_out_ep ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      frame ,  IRDA_USB_SPEED_MTU , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      speed_bulk_callback ,  self ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									urb - > transfer_buffer_length  =  self - > header_length ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[PATCH] USB: URB_ASYNC_UNLINK flag removed from the kernel
29 July 2005, Cambridge, MA:
This afternoon Alan Stern submitted a patch to remove the URB_ASYNC_UNLINK
flag from the Linux kernel.  Mr. Stern explained, "This flag is a relic
from an earlier, less-well-designed system.  For over a year it hasn't
been used for anything other than printing warning messages."
An anonymous spokesman for the Linux kernel development community
commented, "This is exactly the sort of thing we see happening all the
time.  As the kernel evolves, support for old techniques and old code can
be jettisoned and replaced by newer, better approaches.  Proprietary
operating systems do not have the freedom or flexibility to change so
quickly."
Mr. Stern, a staff member at Harvard University's Rowland Institute who
works on Linux only as a hobby, noted that the patch (labelled as548) did
not update two files, keyspan.c and option.c, in the USB drivers' "serial"
subdirectory.  "Those files need more extensive changes," he remarked.
"They examine the status field of several URBs at times when they're not
supposed to.  That will need to be fixed before the URB_ASYNC_UNLINK flag
is removed."
Greg Kroah-Hartman, the kernel maintainer responsible for overseeing all
of Linux's USB drivers, did not respond to our inquiries or return our
calls.  His only comment was "Applied, thanks."
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
											 
										 
										
											2005-07-29 16:11:07 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									urb - > transfer_flags  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Irq disabled -> GFP_ATOMIC */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( ret  =  usb_submit_urb ( urb ,  GFP_ATOMIC ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), failed Speed URB \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Speed  URB  callback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Now ,  we  can  only  get  called  for  the  speed  URB . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around.  On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable.  On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions.  Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller.  A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs.  Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
	struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
	set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
	-	update_process_times(user_mode(regs));
	-	profile_tick(CPU_PROFILING, regs);
	+	update_process_times(user_mode(get_irq_regs()));
	+	profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
 (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
     the input_dev struct.
 (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
     something different depending on whether it's been supplied with a regs
     pointer or not.
 (*) Various IRQ handler function pointers have been moved to type
     irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
											 
										 
										
											2006-10-05 14:55:46 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  speed_bulk_callback ( struct  urb  * urb )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We should always have a context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We should always be called for the speed URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( urb  = =  self - > speed_urb ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check for timeout and other USB nasties */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* I get a lot of -ECONNABORTED = -103 here - Jean II */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s(), URB complete status %d, transfer_flags 0x%04X \n " ,  __func__ ,  urb - > status ,  urb - > transfer_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Don't do anything here, that might confuse the USB layer.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Instead ,  we  will  wait  for  irda_usb_net_timeout ( ) ,  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  network  layer  watchdog ,  to  fix  the  situation . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* A reset of the dongle might be welcomed here - Jean II */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* urb is now available */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//urb->status = 0; -> tested above
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* New speed and xbof is now commited in hardware */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > new_speed  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > new_xbofs  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allow the stack to send more packets */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_wake_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Send  an  IrDA  frame  to  the  USB  dongle  ( for  transmission ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-08-31 19:50:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  netdev_tx_t  irda_usb_hard_xmit ( struct  sk_buff  * skb ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    struct  net_device  * netdev ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  netdev_priv ( netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  urb  * urb  =  self - > tx_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s32  speed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									s16  xbofs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  res ,  mtt ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 4 ,  " %s() on %s \n " ,  __func__ ,  netdev - > name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_stop_queue ( netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Protect us from USB callbacks, net watchdog and else. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check if the device is still there.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  We  need  to  check  self - > present  under  the  spinlock  because 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  of  irda_usb_disconnect ( )  is  synchronous  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > present )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s(), Device is gone... \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  drop ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check if we need to change the number of xbofs */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        xbofs  =  irda_get_next_xbofs ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ( xbofs  ! =  self - > xbofs )  & &  ( xbofs  ! =  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > new_xbofs  =  xbofs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /* Check if we need to change the speed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									speed  =  irda_get_next_speed ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( speed  ! =  self - > speed )  & &  ( speed  ! =  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Set the desired speed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > new_speed  =  speed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check for empty frame */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! skb - > len )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* IrLAP send us an empty frame to make us change the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  speed .  Changing  speed  with  the  USB  adapter  is  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  fact  sending  an  empty  frame  to  the  adapter ,  so  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  could  just  let  the  present  function  do  its  job . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  However ,  we  would  wait  for  min  turn  time , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  do  an  extra  memcpy  and  increment  packet  counters . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											irda_usb_change_speed_xbofs ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											netdev - > trans_start  =  jiffies ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Will netif_wake_queue() in callback */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  drop ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), URB still in use! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  drop ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-03-27 18:55:52 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									skb_copy_from_linear_data ( skb ,  self - > tx_buff  +  self - > header_length ,  skb - > len ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Change setting for next frame */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_STIR421X )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										__u8  turnaround_time ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										__u8 *  frame  =  self - > tx_buff ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										turnaround_time  =  get_turnaround_time (  skb  ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_usb_build_header ( self ,  frame ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										frame [ 2 ]  =  turnaround_time ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( skb - > len  ! =  0 )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( ( skb - > len  %  128 )  = =  0 )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( ( skb - > len  %  512 )  ! =  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* add extra byte for special SigmaTel feature */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											frame [ 1 ]  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											skb_put ( skb ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											frame [ 1 ]  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										irda_usb_build_header ( self ,  self - > tx_buff ,  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* FIXME: Make macro out of this one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									( ( struct  irda_skb_cb  * ) skb - > cb ) - > context  =  self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									usb_fill_bulk_urb ( urb ,  self - > usbdev , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										      usb_sndbulkpipe ( self - > usbdev ,  self - > bulk_out_ep ) , 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                      self - > tx_buff ,  skb - > len  +  self - > header_length , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                      write_bulk_callback ,  skb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* This flag (URB_ZERO_PACKET) indicates that what we send is not
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  a  continuous  stream  of  data  but  separate  packets . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  In  this  case ,  the  USB  layer  will  insert  an  empty  USB  frame  ( TD ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  after  each  of  our  packets  that  is  exact  multiple  of  the  frame  size . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  This  is  how  the  dongle  will  detect  the  end  of  packet  -  Jean  II  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[PATCH] USB: URB_ASYNC_UNLINK flag removed from the kernel
29 July 2005, Cambridge, MA:
This afternoon Alan Stern submitted a patch to remove the URB_ASYNC_UNLINK
flag from the Linux kernel.  Mr. Stern explained, "This flag is a relic
from an earlier, less-well-designed system.  For over a year it hasn't
been used for anything other than printing warning messages."
An anonymous spokesman for the Linux kernel development community
commented, "This is exactly the sort of thing we see happening all the
time.  As the kernel evolves, support for old techniques and old code can
be jettisoned and replaced by newer, better approaches.  Proprietary
operating systems do not have the freedom or flexibility to change so
quickly."
Mr. Stern, a staff member at Harvard University's Rowland Institute who
works on Linux only as a hobby, noted that the patch (labelled as548) did
not update two files, keyspan.c and option.c, in the USB drivers' "serial"
subdirectory.  "Those files need more extensive changes," he remarked.
"They examine the status field of several URBs at times when they're not
supposed to.  That will need to be fixed before the URB_ASYNC_UNLINK flag
is removed."
Greg Kroah-Hartman, the kernel maintainer responsible for overseeing all
of Linux's USB drivers, did not respond to our inquiries or return our
calls.  His only comment was "Applied, thanks."
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
											 
										 
										
											2005-07-29 16:11:07 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									urb - > transfer_flags  =  URB_ZERO_PACKET ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Generate min turn time. FIXME: can we do better than this? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Trying to a turnaround time at this level is trying to measure
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  processor  clock  cycle  with  a  wrist - watch ,  approximate  at  best . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  What  we  know  is  the  last  time  we  received  a  frame  over  USB . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Due  to  latency  over  USB  that  depend  on  the  USB  load ,  we  don ' t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  know  when  this  frame  was  received  over  IrDA  ( a  few  ms  before  ? ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Then ,  same  story  for  our  outgoing  frame . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  In  theory ,  the  USB  dongle  is  supposed  to  handle  the  turnaround 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  by  itself  ( spec  1.0 ,  chater  4 ,  page  6 ) .  Who  knows  ? ? ?  That ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  why  this  code  is  enabled  only  for  dongles  that  doesn ' t  meet 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  the  spec . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_NO_TURN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mtt  =  irda_get_mtt ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( mtt )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  diff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_gettimeofday ( & self - > now ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											diff  =  self - > now . tv_usec  -  self - > stamp . tv_usec ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef IU_USB_MIN_RTT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Factor in USB delays -> Get rid of udelay() that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  would  be  lost  in  the  noise  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											diff  + =  IU_USB_MIN_RTT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  /* IU_USB_MIN_RTT */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If the usec counter did wraparound, the diff will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  go  negative  ( tv_usec  is  a  long ) ,  so  we  need  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  correct  it  by  one  second .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( diff  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												diff  + =  1000000 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										        /* Check if the mtt is larger than the time we have
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  already  used  by  all  the  protocol  processing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( mtt  >  diff )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												mtt  - =  diff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( mtt  >  1000 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													mdelay ( mtt / 1000 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													udelay ( mtt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( res  =  usb_submit_urb ( urb ,  GFP_ATOMIC ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), failed Tx URB \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										netdev - > stats . tx_errors + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* Let USB recover : We will catch that in the watchdog */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*netif_start_queue(netdev);*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Increment packet stats */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										netdev - > stats . tx_packets + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                netdev - > stats . tx_bytes  + =  skb - > len ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										netdev - > trans_start  =  jiffies ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2009-06-23 06:03:08 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NETDEV_TX_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								drop :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Drop silently the skb and exit */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dev_kfree_skb ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-06-12 03:17:19 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  NETDEV_TX_OK ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  :  this  function  will  be  called  only  for  tx_urb . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around.  On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable.  On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions.  Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller.  A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs.  Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
	struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
	set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
	-	update_process_times(user_mode(regs));
	-	profile_tick(CPU_PROFILING, regs);
	+	update_process_times(user_mode(get_irq_regs()));
	+	profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
 (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
     the input_dev struct.
 (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
     something different depending on whether it's been supplied with a regs
     pointer or not.
 (*) Various IRQ handler function pointers have been moved to type
     irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
											 
										 
										
											2006-10-05 14:55:46 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  write_bulk_callback ( struct  urb  * urb )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sk_buff  * skb  =  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  ( ( struct  irda_skb_cb  * )  skb - > cb ) - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We should always have a context */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We should always be called for the speed URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( urb  = =  self - > tx_urb ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Free up the skb */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dev_kfree_skb_any ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check for timeout and other USB nasties */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* I get a lot of -ECONNABORTED = -103 here - Jean II */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s(), URB complete status %d, transfer_flags 0x%04X \n " ,  __func__ ,  urb - > status ,  urb - > transfer_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Don't do anything here, that might confuse the USB layer,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  and  we  could  go  in  recursion  and  blow  the  kernel  stack . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Instead ,  we  will  wait  for  irda_usb_net_timeout ( ) ,  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  network  layer  watchdog ,  to  fix  the  situation . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* A reset of the dongle might be welcomed here - Jean II */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* urb is now available */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//urb->status = 0; -> tested above
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Make sure we read self->present properly */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If the network is closed, stop everything */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( ! self - > netopen )  | |  ( ! self - > present ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s(), Network is gone... \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If changes to speed or xbofs is pending... */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( self - > new_speed  ! =  - 1 )  | |  ( self - > new_xbofs  ! =  - 1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( self - > new_speed  ! =  self - > speed )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( self - > new_xbofs  ! =  self - > xbofs ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We haven't changed speed yet (because of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  IUC_SPEED_BUG ) ,  so  do  it  now  -  Jean  II  */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											IRDA_DEBUG ( 1 ,  " %s(), Changing speed now... \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											irda_usb_change_speed_xbofs ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* New speed and xbof is now commited in hardware */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_speed  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_xbofs  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Done, waiting for next packet */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											netif_wake_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Otherwise, allow the stack to send more packets */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										netif_wake_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Watchdog  timer  from  the  network  layer . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  After  a  predetermined  timeout ,  if  we  don ' t  give  confirmation  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  packet  has  been  sent  ( i . e .  no  call  to  netif_wake_queue ( ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  the  network  layer  will  call  this  function . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  that  URB  that  we  submit  have  also  a  timeout .  When  the  URB  timeout 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  expire ,  the  normal  URB  callback  is  called  ( write_bulk_callback ( ) ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_net_timeout ( struct  net_device  * netdev )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  netdev_priv ( netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  urb  * urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int 	done  =  0 ; 	/* If we have made any progress */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 0 ,  " %s(), Network layer thinks we timed out! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Protect us from USB callbacks, net Tx and else. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* self->present *MUST* be read under spinlock */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > present )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), device not present! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										netif_stop_queue ( netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check speed URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb  =  self - > speed_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X \n " ,  netdev - > name ,  urb - > status ,  urb - > transfer_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( urb - > status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - EINPROGRESS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											usb_unlink_urb ( urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Note : above will  *NOT* call netif_wake_queue()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  in  completion  handler ,  we  will  come  back  here . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											done  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-18 22:49:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  - ECONNRESET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - ENOENT : 			/* urb unlinked by us */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										default : 			/* ??? - Play safe */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											urb - > status  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											netif_wake_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											done  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check Tx URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb  =  self - > tx_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sk_buff  * skb  =  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X \n " ,  netdev - > name ,  urb - > status ,  urb - > transfer_flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Increase error count */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										netdev - > stats . tx_errors + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef IU_BUG_KICK_TIMEOUT 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Can't be a bad idea to reset the speed ;-) - Jean II */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( self - > new_speed  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_speed  =  self - > speed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( self - > new_xbofs  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_xbofs  =  self - > xbofs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_usb_change_speed_xbofs ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  /* IU_BUG_KICK_TIMEOUT */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( urb - > status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - EINPROGRESS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											usb_unlink_urb ( urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Note : above will  *NOT* call netif_wake_queue()
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  in  completion  handler ,  because  urb - > status  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  be  - ENOENT .  We  will  fix  that  at  the  next  watchdog , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  leaving  more  time  to  USB  to  recover . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											done  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-18 22:49:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  - ECONNRESET : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - ENOENT : 			/* urb unlinked by us */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										default : 			/* ??? - Play safe */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if ( skb  ! =  NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dev_kfree_skb_any ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											urb - > status  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											netif_wake_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											done  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Maybe we need a reset */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : Some drivers seem to use a usb_set_interface() when they
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  need  to  reset  the  hardware .  Hum . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* if(done == 0) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/************************* RECEIVE ROUTINES *************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Receive  packets  from  the  USB  layer  stack  and  pass  them  to  the  IrDA  stack . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Try  to  work  around  USB  failures . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Some  of  you  may  have  noticed  that  most  dongle  have  an  interrupt  in  pipe 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  that  we  don ' t  use .  Here  is  the  little  secret . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  When  we  hang  a  Rx  URB  on  the  bulk  in  pipe ,  it  generates  some  USB  traffic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  in  every  USB  frame .  This  is  unnecessary  overhead . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  interrupt  in  pipe  will  generate  an  event  every  time  a  packet  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  received .  Reading  an  interrupt  pipe  adds  minimal  overhead ,  but  has  some 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  latency  ( ~ 1 ms ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  we  are  connected  ( speed  ! =  9600 ) ,  we  want  to  minimise  latency ,  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  we  just  always  hang  the  Rx  URB  and  ignore  the  interrupt . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  If  we  are  not  connected  ( speed  = =  9600 ) ,  there  is  usually  no  Rx  traffic , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  and  we  want  to  minimise  the  USB  overhead .  In  this  case  we  should  wait 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  on  the  interrupt  pipe  and  hang  the  Rx  URB  only  when  an  interrupt  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  received . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  :  don ' t  read  the  above  as  what  we  are  currently  doing ,  but  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  something  we  could  do  with  KC  dongle .  Also  don ' t  forget  that  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  interrupt  pipe  is  not  part  of  the  original  standard ,  so  this  would 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  need  to  be  optional . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Submit  a  Rx  URB  to  the  USB  layer  to  handle  reception  of  a  frame 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Mostly  called  by  the  completion  callback  of  the  previous  URB . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_submit ( struct  irda_usb_cb  * self ,  struct  sk_buff  * skb ,  struct  urb  * urb )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_skb_cb  * cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* This should never happen */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( skb  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( urb  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Save ourselves in the skb */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cb  =  ( struct  irda_skb_cb  * )  skb - > cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cb - > context  =  self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Reinitialize URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_fill_bulk_urb ( urb ,  self - > usbdev ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      usb_rcvbulkpipe ( self - > usbdev ,  self - > bulk_in_ep ) ,  
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										      skb - > data ,  IRDA_SKB_MAX_MTU , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                      irda_usb_receive ,  skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb - > status  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  usb_submit_urb ( urb ,  GFP_ATOMIC ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ret )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If this ever happen, we are in deep s***.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Basically ,  the  Rx  path  will  stop . . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), Failed to submit Rx URB %d \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											     __func__ ,  ret ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_receive ( urb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *      Called  by  the  USB  subsystem  when  a  frame  has  been  received 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around.  On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable.  On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions.  Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller.  A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386.  I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs.  Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
	struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
	set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
	-	update_process_times(user_mode(regs));
	-	profile_tick(CPU_PROFILING, regs);
	+	update_process_times(user_mode(get_irq_regs()));
	+	profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
 (*) input_dev() is now gone entirely.  The regs pointer is no longer stored in
     the input_dev struct.
 (*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking.  It does
     something different depending on whether it's been supplied with a regs
     pointer or not.
 (*) Various IRQ handler function pointers have been moved to type
     irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
											 
										 
										
											2006-10-05 14:55:46 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  irda_usb_receive ( struct  urb  * urb )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sk_buff  * skb  =  ( struct  sk_buff  * )  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ;  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_skb_cb  * cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sk_buff  * newskb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sk_buff  * dataskb ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  urb  * next_urb ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-03-15 14:57:19 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  len ,  docopy ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s(), len=%d \n " ,  __func__ ,  urb - > actual_length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find ourselves */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cb  =  ( struct  irda_skb_cb  * )  skb - > cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( cb  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self  =  ( struct  irda_usb_cb  * )  cb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If the network is closed or the device gone, stop everything */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ( ! self - > netopen )  | |  ( ! self - > present ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_DEBUG ( 0 ,  " %s(), Network is gone! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* Don't re-submit the URB : will stall the Rx path */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check the status */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( urb - > status  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( urb - > status )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - EILSEQ : 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											self - > netdev - > stats . rx_crc_errors + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Also precursor to a hot-unplug on UHCI. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Fallthrough... */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-18 22:49:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  - ECONNRESET : 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Random error, if I remember correctly */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											/* uhci_cleanup_unlink() is going to kill the Rx
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  URB  just  after  we  return .  No  problem ,  at  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  point  the  URB  will  be  idle  ; - )  -  Jean  II  */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-18 22:49:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  - ESHUTDOWN : 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* That's usually a hot-unplug. Submit will fail... */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-09-18 22:49:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  - ETIME : 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Usually precursor to a hot-unplug on OHCI. */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											self - > netdev - > stats . rx_errors + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											IRDA_DEBUG ( 0 ,  " %s(), RX status %d, transfer_flags 0x%04X  \n " ,  __func__ ,  urb - > status ,  urb - > transfer_flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* If we received an error, we don't want to resubmit the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Rx  URB  straight  away  but  to  give  the  USB  layer  a  little 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  bit  of  breathing  room . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  We  are  in  the  USB  thread  context ,  therefore  there  is  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  danger  of  recursion  ( new  URB  we  submit  fails ,  we  come 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  back  here ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  With  recent  USB  stack  ( 2.6 .15 + ) ,  I ' m  seeing  that  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  hot  unplug  of  the  dongle . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Lowest  effective  timer  is  10 ms . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Jean  II  */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-18 08:22:05 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > rx_defer_timer . function  =  irda_usb_rx_defer_expired ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > rx_defer_timer . data  =  ( unsigned  long )  urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mod_timer ( & self - > rx_defer_timer ,  jiffies  +  ( 10  *  HZ  /  1000 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check for empty frames */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( urb - > actual_length  < =  self - > header_length )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), empty frame! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  done ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*  
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Remember  the  time  we  received  this  frame ,  so  we  can 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  reduce  the  min  turn  time  a  bit  since  we  will  know 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  how  much  time  we  have  used  for  protocol  processing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        do_gettimeofday ( & self - > stamp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Check if we need to copy the data to a new skb or not.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  For  most  frames ,  we  use  ZeroCopy  and  pass  the  already 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  allocated  skb  up  the  stack . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  If  the  frame  is  small ,  it  is  more  efficient  to  copy  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  save  memory  ( copy  will  be  fast  anyway  -  that ' s 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  called  Rx - copy - break ) .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									docopy  =  ( urb - > actual_length  <  IRDA_RX_COPY_THRESHOLD ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate a new skb */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_STIR421X ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										newskb  =  dev_alloc_skb ( docopy  ?  urb - > actual_length  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       IRDA_SKB_MAX_MTU  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       USB_IRDA_STIR421X_HEADER ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										newskb  =  dev_alloc_skb ( docopy  ?  urb - > actual_length  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       IRDA_SKB_MAX_MTU ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ! newskb )   { 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > netdev - > stats . rx_dropped + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* We could deliver the current skb, but this would stall
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  the  Rx  path .  Better  drop  the  packet . . .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  done ;   
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Make sure IP header get aligned (IrDA header is 5 bytes) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* But IrDA-USB header is 1 byte. Jean II */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//skb_reserve(newskb, USB_IRDA_HEADER - 1);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( docopy )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Copy packet, so we can recycle the original */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-27 18:55:52 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										skb_copy_from_linear_data ( skb ,  newskb - > data ,  urb - > actual_length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* Deliver this new skb */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dataskb  =  newskb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* And hook the old skb to the URB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  Note  :  we  don ' t  need  to  " clean up "  the  old  skb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  as  we  never  touched  it .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We are using ZeroCopy. Deliver old skb */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dataskb  =  skb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* And hook the new skb to the URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										skb  =  newskb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Set proper length on skb & remove USB-IrDA header */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									skb_put ( dataskb ,  urb - > actual_length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									skb_pull ( dataskb ,  self - > header_length ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ask the networking layer to queue the packet for the IrDA stack */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dataskb - > dev  =  self - > netdev ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-19 15:30:44 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									skb_reset_mac_header ( dataskb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									dataskb - > protocol  =  htons ( ETH_P_IRDA ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-03-15 14:57:19 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									len  =  dataskb - > len ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									netif_rx ( dataskb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Keep stats up to date */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-06 10:40:43 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > netdev - > stats . rx_bytes  + =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > netdev - > stats . rx_packets + + ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								done :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : at this point, the URB we've just received (urb)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  is  still  referenced  by  the  USB  layer .  For  example ,  if  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  have  received  a  - ECONNRESET ,  uhci_cleanup_unlink ( )  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  continue  to  process  it  ( in  fact ,  cleaning  it  up ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  If  we  were  to  submit  this  URB ,  disaster  would  ensue . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Therefore ,  we  submit  our  idle  URB ,  and  put  this  URB  in  our 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  idle  slot . . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : with this scheme, we could submit the idle URB before
 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  processing  the  Rx  URB .  I  don ' t  think  it  would  buy  us  anything  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  we  are  running  in  the  USB  thread  context .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									next_urb  =  self - > idle_rx_urb ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Recycle Rx URB : Now, the idle URB is the present one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > idle_rx_urb  =  urb ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Submit the idle URB to replace the URB we've just received.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Do  it  last  to  avoid  race  conditions . . .  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_usb_submit ( self ,  skb ,  next_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  In  case  of  errors ,  we  want  the  USB  layer  to  have  time  to  recover . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Now ,  it  is  time  to  resubmit  ouur  Rx  URB . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_rx_defer_expired ( unsigned  long  data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  urb  * urb  =  ( struct  urb  * )  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  sk_buff  * skb  =  ( struct  sk_buff  * )  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ;  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_skb_cb  * cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  urb  * next_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find ourselves */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cb  =  ( struct  irda_skb_cb  * )  skb - > cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( cb  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self  =  ( struct  irda_usb_cb  * )  cb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Same stuff as when Rx is done, see above... */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									next_urb  =  self - > idle_rx_urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > idle_rx_urb  =  urb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_usb_submit ( self ,  skb ,  next_urb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Callbak  from  IrDA  layer .  IrDA  wants  to  know  if  we  have 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  started  receiving  anything . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_is_receiving ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : because of the way UHCI works, it's almost impossible
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  get  this  info .  The  Controller  DMA  directly  to  memory  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  signal  only  when  the  whole  frame  is  finished .  To  know  if  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  first  TD  of  the  URB  has  been  filled  or  not  seems  hard  work . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  The  other  solution  would  be  to  use  the  " receiving "  command 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  on  the  default  decriptor  with  a  usb_control_msg ( ) ,  but  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  would  add  USB  traffic  and  would  return  result  only  in  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  next  USB  frame  ( ~ 1 ms ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  I ' ve  been  told  that  current  dongles  send  status  info  on  their 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  interrupt  endpoint ,  and  that ' s  what  the  Windows  driver  uses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  know  this  info .  Unfortunately ,  this  is  not  yet  in  the  spec . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ;  /* For now */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# define STIR421X_PATCH_PRODUCT_VER     "Product Version: " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define STIR421X_PATCH_STMP_TAG        "STMP" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define STIR421X_PATCH_CODE_OFFSET     512  /* patch image starts before here */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* marks end of patch file header (PC DOS text file EOF character) */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define STIR421X_PATCH_END_OF_HDR_TAG  0x1A 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define STIR421X_PATCH_BLOCK_SIZE      1023 
  
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Function  stir421x_fwupload  ( struct  irda_usb_cb  * self , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *                              unsigned  char  * patch , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *                              const  unsigned  int  patch_len ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    Upload  firmware  code  to  SigmaTel  421 X  IRDA - USB  dongle 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  stir421x_fw_upload ( struct  irda_usb_cb  * self ,  
						 
					
						
							
								
									
										
										
										
											2008-05-24 00:10:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											     const  unsigned  char  * patch , 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											     const  unsigned  int  patch_len ) 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        int  ret  =  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        int  actual_len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unsigned  int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unsigned  int  block_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unsigned  char  * patch_block ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        patch_block  =  kzalloc ( STIR421X_PATCH_BLOCK_SIZE ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( patch_block  = =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* break up patch into 1023-byte sections */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  patch_len ;  i  + =  block_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										block_size  =  patch_len  -  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( block_size  >  STIR421X_PATCH_BLOCK_SIZE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											block_size  =  STIR421X_PATCH_BLOCK_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* upload the patch section */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( patch_block ,  patch  +  i ,  block_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  =  usb_bulk_msg ( self - > usbdev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												   usb_sndbulkpipe ( self - > usbdev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   self - > bulk_out_ep ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												   patch_block ,  block_size , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												   & actual_len ,  msecs_to_jiffies ( 500 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_DEBUG ( 3 , " %s(): Bulk send %u bytes, ret=%d \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											   __func__ ,  actual_len ,  ret ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ret  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-16 20:28:36 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mdelay ( 10 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( patch_block ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 } 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  stir421x_patch_device ( struct  irda_usb_cb  * self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Get  a  firmware  code  from  userspase  using  hotplug  request_firmware ( )  call 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  stir421x_patch_device ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-05-24 00:10:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-01-14 20:55:00 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  stir421x_fw_name [ 12 ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-05-24 00:10:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									const  struct  firmware  * fw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									const  unsigned  char  * fw_version_ptr ;  /* pointer to version string */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  long  fw_version  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  Known  firmware  patch  file  names  for  STIR421x  dongles 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  are  " 42101001.sb "  or  " 42101002.sb " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sprintf ( stir421x_fw_name ,  " 4210%4X.sb " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self - > usbdev - > descriptor . bcdDevice ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ret  =  request_firmware ( & fw ,  stir421x_fw_name ,  & self - > usbdev - > dev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ret  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        /* We get a patch from userspace */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-25 05:49:19 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        IRDA_MESSAGE ( " %s(): Received firmware %s (%zu bytes) \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                     __func__ ,  stir421x_fw_name ,  fw - > size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ret  =  - EINVAL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get the bcd product version */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! memcmp ( fw - > data ,  STIR421X_PATCH_PRODUCT_VER , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    sizeof ( STIR421X_PATCH_PRODUCT_VER )  -  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                fw_version_ptr  =  fw - > data  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											sizeof ( STIR421X_PATCH_PRODUCT_VER )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                /* Let's check if the product version is dotted */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( fw_version_ptr [ 3 ]  = =  ' . '  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    fw_version_ptr [ 7 ]  = =  ' . ' )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											unsigned  long  major ,  minor ,  build ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											major  =  simple_strtoul ( fw_version_ptr ,  NULL ,  10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											minor  =  simple_strtoul ( fw_version_ptr  +  4 ,  NULL ,  10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											build  =  simple_strtoul ( fw_version_ptr  +  8 ,  NULL ,  10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											fw_version  =  ( major  < <  12 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												+  ( minor  < <  8 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												+  ( ( build  /  10 )  < <  4 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												+  ( build  %  10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											IRDA_DEBUG ( 3 ,  " %s(): Firmware Product version %ld \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                   __func__ ,  fw_version ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-05-21 06:32:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( self - > usbdev - > descriptor . bcdDevice  = =  cpu_to_le16 ( fw_version ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                /*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  If  we ' re  here ,  we ' ve  found  a  correct  patch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 *  The  actual  image  starts  after  the  " STMP "  keyword 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 *  so  forward  to  the  firmware  header  tag 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-03 07:58:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                for  ( i  =  0 ;  ( fw - > data [ i ]  ! =  STIR421X_PATCH_END_OF_HDR_TAG )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     ( i  <  fw - > size ) ;  i + + )  ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                /* here we check for the out of buffer case */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-12-03 07:58:21 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  ( ( STIR421X_PATCH_END_OF_HDR_TAG  = =  fw - > data [ i ] )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ( i  <  STIR421X_PATCH_CODE_OFFSET ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        if  ( ! memcmp ( fw - > data  +  i  +  1 ,  STIR421X_PATCH_STMP_TAG , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    sizeof ( STIR421X_PATCH_STMP_TAG )  -  1 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* We can upload the patch to the target */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												i  + =  sizeof ( STIR421X_PATCH_STMP_TAG ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                ret  =  stir421x_fw_upload ( self ,  & fw - > data [ i ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															 fw - > size  -  i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        release_firmware ( fw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/********************** IRDA DEVICE CALLBACKS **********************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Main  calls  from  the  IrDA / Network  subsystem . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Mostly  registering  a  new  irda - usb  device  and  removing  it . . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  We  only  deal  with  the  IrDA  side  of  the  business ,  the  USB  side  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  be  dealt  with  below . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_net_open  ( dev ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     Network  device  is  taken  up .  Usually  this  is  done  by  " ifconfig irda0 up "  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Note  :  don ' t  mess  with  self - > netopen  -  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_open ( struct  net_device  * netdev )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-12-16 14:07:36 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									char 	hwname [ 16 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( netdev  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self  =  netdev_priv ( netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-12-16 14:07:36 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Can only open the device if it's there */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( ! self - > present )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-12-16 14:07:36 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), device not present! \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if ( self - > needspatch )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-12-16 14:07:36 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_WARNING ( " %s(), device needs patch \n " ,  __func__ )  ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - EIO  ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Initialise default speed and xbofs value
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  ( IrLAP  will  change  that  soon )  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > speed  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > xbofs  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > new_speed  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > new_xbofs  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* To do *before* submitting Rx urbs and starting net Tx queue
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > netopen  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-12-16 14:07:36 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Now  that  everything  should  be  initialized  properly , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Open  new  IrLAP  layer  instance  to  take  care  of  us . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Note  :  will  send  immediately  a  speed  change . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sprintf ( hwname ,  " usb#%d " ,  self - > usbdev - > devnum ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > irlap  =  irlap_open ( netdev ,  & self - > qos ,  hwname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self - > irlap  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allow IrLAP to send data to us */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_start_queue ( netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We submit all the Rx URB except for one that we keep idle.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Need  to  be  initialised  before  submitting  other  USBs ,  because 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  in  some  cases  as  soon  as  we  submit  the  URBs  the  USB  layer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  will  trigger  a  dummy  receive  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > idle_rx_urb  =  self - > rx_urb [ IU_MAX_ACTIVE_RX_URBS ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > idle_rx_urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Now that we can pass data to IrLAP, allow the USB layer
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  to  send  us  some  data . . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  IU_MAX_ACTIVE_RX_URBS ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sk_buff  * skb  =  dev_alloc_skb ( IRDA_SKB_MAX_MTU ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! skb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If this ever happen, we are in deep s***.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Basically ,  we  can ' t  start  the  Rx  path . . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											IRDA_WARNING ( " %s(), Failed to allocate Rx skb \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												     __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										//skb_reserve(newskb, USB_IRDA_HEADER - 1);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_usb_submit ( self ,  skb ,  self - > rx_urb [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Ready to play !!! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_net_close  ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     Network  device  is  taken  down .  Usually  this  is  done  by  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     " ifconfig irda0 down "  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_close ( struct  net_device  * netdev )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int 	i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( netdev  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self  =  netdev_priv ( netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Clear this flag *before* unlinking the urbs and *before*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  stopping  the  network  Tx  queue  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > netopen  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Stop network Tx queue */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_stop_queue ( netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Kill defered Rx URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									del_timer ( & self - > rx_defer_timer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Deallocate all the Rx path buffers (URBs and skb) */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										struct  urb  * urb  =  self - > rx_urb [ i ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  sk_buff  * skb  =  ( struct  sk_buff  * )  urb - > context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Cancel the receive command */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usb_kill_urb ( urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* The skb is ours, free it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( skb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dev_kfree_skb ( skb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											urb - > context  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Cancel Tx and speed URB - need to be synchronous to avoid races */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_kill_urb ( self - > tx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_kill_urb ( self - > speed_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Stop and remove instance of IrLAP */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > irlap ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irlap_close ( self - > irlap ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > irlap  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  IOCTLs  :  Extra  out - of - band  network  commands . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_net_ioctl ( struct  net_device  * dev ,  struct  ifreq  * rq ,  int  cmd )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  if_irda_req  * irq  =  ( struct  if_irda_req  * )  rq ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( dev  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self  =  netdev_priv ( dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									IRDA_ASSERT ( self  ! =  NULL ,  return  - 1 ; ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 2 ,  " %s(), %s, (cmd=0x%X) \n " ,  __func__ ,  dev - > name ,  cmd ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( cmd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SIOCSBANDWIDTH :  /* Set bandwidth */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! capable ( CAP_NET_ADMIN ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EPERM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Protect us from USB callbacks, net watchdog and else. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check if the device is still there */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( self - > present )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Set the desired speed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											self - > new_speed  =  irq - > ifr_baudrate ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											irda_usb_change_speed_xbofs ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SIOCSMEDIABUSY :  /* Set media busy */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! capable ( CAP_NET_ADMIN ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EPERM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check if the IrDA stack is still there */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( self - > netopen ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											irda_device_set_media_busy ( self - > netdev ,  TRUE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  SIOCGRECEIVING :  /* Check if we are receiving right now */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irq - > ifr_receiving  =  irda_usb_is_receiving ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  =  - EOPNOTSUPP ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/********************* IRDA CONFIG SUBROUTINES *********************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Various  subroutines  dealing  with  IrDA  and  network  stuff  we  use  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  configure  and  initialise  each  irda - usb  instance . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  These  functions  are  used  below  in  the  main  calls  of  the  driver . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Set  proper  values  in  the  IrDA  QOS  structure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  irda_usb_init_qos ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_class_desc  * desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 3 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									desc  =  self - > irda_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Initialize QoS for this device */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_init_max_qos_capabilies ( & self - > qos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* See spec section 7.2 for meaning.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Values  are  little  endian  ( as  most  USB  stuff ) ,  the  IrDA  stack 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  use  it  in  native  order  ( see  parameters . c ) .  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > qos . baud_rate . bits        =  le16_to_cpu ( desc - > wBaudRate ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > qos . min_turn_time . bits    =  desc - > bmMinTurnaroundTime ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > qos . additional_bofs . bits  =  desc - > bmAdditionalBOFs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > qos . window_size . bits      =  desc - > bmWindowSize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > qos . data_size . bits        =  desc - > bmDataSize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_DEBUG ( 0 ,  " %s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X \n " ,  
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										__func__ ,  self - > qos . baud_rate . bits ,  self - > qos . data_size . bits ,  self - > qos . window_size . bits ,  self - > qos . additional_bofs . bits ,  self - > qos . min_turn_time . bits ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Don't always trust what the dongle tell us */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( self - > capability  &  IUC_SIR_ONLY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . baud_rate . bits 	& =  0x00ff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( self - > capability  &  IUC_SMALL_PKT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . data_size . bits 	 =  0x07 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( self - > capability  &  IUC_NO_WINDOW ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . window_size . bits 	 =  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( self - > capability  &  IUC_MAX_WINDOW ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . window_size . bits 	 =  0x7f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( self - > capability  &  IUC_MAX_XBOFS ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . additional_bofs . bits 	 =  0x01 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Module parameter can override the rx window size */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( qos_mtt_bits ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > qos . min_turn_time . bits  =  qos_mtt_bits ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif	     
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Note  :  most  of  those  values  apply  only  for  the  receive  path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  the  transmit  path  will  be  set  differently  -  Jean  II  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_qos_bits_to_value ( & self - > qos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
									
										
										
										
											2009-03-20 19:35:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  struct  net_device_ops  irda_usb_netdev_ops  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. ndo_open        =  irda_usb_net_open , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. ndo_stop        =  irda_usb_net_close , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. ndo_do_ioctl    =  irda_usb_net_ioctl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. ndo_start_xmit  =  irda_usb_hard_xmit , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. ndo_tx_timeout 	=  irda_usb_net_timeout , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Initialise  the  network  side  of  the  irda - usb  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Called  when  a  new  USB  instance  is  registered  in  irda_usb_probe ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  int  irda_usb_open ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  net_device  * netdev  =  self - > netdev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-20 19:35:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									netdev - > netdev_ops  =  & irda_usb_netdev_ops ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-03-20 19:35:35 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									irda_usb_init_qos ( self ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  register_netdev ( netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Cleanup  the  network  side  of  the  irda - usb  instance 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Called  when  a  USB  instance  is  removed  in  irda_usb_disconnect ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  irda_usb_close ( struct  irda_usb_cb  * self )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Remove netdevice */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unregister_netdev ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Remove the speed buffer */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-10-28 16:53:13 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( self - > speed_buff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > speed_buff  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( self - > tx_buff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > tx_buff  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/********************** USB CONFIG SUBROUTINES **********************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Various  subroutines  dealing  with  USB  stuff  we  use  to  configure  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  initialise  each  irda - usb  instance . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  These  functions  are  used  below  in  the  main  calls  of  the  driver . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_parse_endpoints ( dev ,  ifnum ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     Parse  the  various  endpoints  and  find  the  one  we  need . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  endpoint  are  the  pipes  used  to  communicate  with  the  USB  device . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  spec  defines  2  endpoints  of  type  bulk  transfer ,  one  in ,  and  one  out . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  These  are  used  to  pass  frames  back  and  forth  with  the  dongle . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Most  dongle  have  also  an  interrupt  endpoint ,  that  will  be  probably 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  documented  in  the  next  spec . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  int  irda_usb_parse_endpoints ( struct  irda_usb_cb  * self ,  struct  usb_host_endpoint  * endpoint ,  int  ennum )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 		/* Endpoint index in table */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Init : no endpoints */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > bulk_in_ep  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > bulk_out_ep  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > bulk_int_ep  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Let's look at all those endpoints */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for ( i  =  0 ;  i  <  ennum ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* All those variables will get optimised by the compiler,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  so  let ' s  aim  for  clarity . . .  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__u8  ep ; 	/* Endpoint address */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__u8  dir ; 	/* Endpoint direction */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__u8  attr ; 	/* Endpoint attribute */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__u16  psize ; 	/* Endpoint max packet size in bytes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Get endpoint address, direction and attribute */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ep  =  endpoint [ i ] . desc . bEndpointAddress  &  USB_ENDPOINT_NUMBER_MASK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dir  =  endpoint [ i ] . desc . bEndpointAddress  &  USB_ENDPOINT_DIR_MASK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										attr  =  endpoint [ i ] . desc . bmAttributes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										psize  =  le16_to_cpu ( endpoint [ i ] . desc . wMaxPacketSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Is it a bulk endpoint ??? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if ( attr  = =  USB_ENDPOINT_XFER_BULK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We need to find an IN and an OUT */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if ( dir  = =  USB_DIR_IN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* This is our Rx endpoint */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self - > bulk_in_ep  =  ep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* This is our Tx endpoint */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self - > bulk_out_ep  =  ep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self - > bulk_out_mtu  =  psize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if ( ( attr  = =  USB_ENDPOINT_XFER_INT )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   ( dir  = =  USB_DIR_IN ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* This is our interrupt endpoint */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												self - > bulk_int_ep  =  ep ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												IRDA_ERROR ( " %s(), Unrecognised endpoint %02X. \n " ,  __func__ ,  ep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_DEBUG ( 0 ,  " %s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										__func__ ,  self - > bulk_in_ep ,  self - > bulk_out_ep ,  self - > bulk_out_mtu ,  self - > bulk_int_ep ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return ( ( self - > bulk_in_ep  ! =  0 )  & &  ( self - > bulk_out_ep  ! =  0 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef IU_DUMP_CLASS_DESC 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  usb_irda_dump_class_desc ( desc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     Prints  out  the  contents  of  the  IrDA  class  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  void  irda_usb_dump_class_desc ( struct  irda_class_desc  * desc )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Values are little endian */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bLength=%x \n " ,  desc - > bLength ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bDescriptorType=%x \n " ,  desc - > bDescriptorType ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bcdSpecRevision=%x \n " ,  le16_to_cpu ( desc - > bcdSpecRevision ) ) ;  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bmDataSize=%x \n " ,  desc - > bmDataSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bmWindowSize=%x \n " ,  desc - > bmWindowSize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bmMinTurnaroundTime=%d \n " ,  desc - > bmMinTurnaroundTime ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " wBaudRate=%x \n " ,  le16_to_cpu ( desc - > wBaudRate ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bmAdditionalBOFs=%x \n " ,  desc - > bmAdditionalBOFs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bIrdaRateSniff=%x \n " ,  desc - > bIrdaRateSniff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									printk ( " bMaxUnicastList=%x \n " ,  desc - > bMaxUnicastList ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  /* IU_DUMP_CLASS_DESC */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Function  irda_usb_find_class_desc ( intf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *     Returns  instance  of  IrDA  class  descriptor ,  or  NULL  if  not  found 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  class  descriptor  is  some  extra  info  that  IrDA  USB  devices  will 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  offer  to  us ,  describing  their  IrDA  characteristics .  We  will  use  that  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  irda_usb_init_qos ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  inline  struct  irda_class_desc  * irda_usb_find_class_desc ( struct  usb_interface  * intf )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  usb_device  * dev  =  interface_to_usbdev  ( intf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_class_desc  * desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									desc  =  kzalloc ( sizeof ( * desc ) ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! desc ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* USB-IrDA class spec 1.0:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 	6.1 .3 :  Standard  " Get Descriptor "  Device  Request  is  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 	       appropriate  to  retrieve  class - specific  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 	6.2 .5 :  Class  Specific  " Get Class Descriptor "  Interface  Request 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * 	       is  mandatory  and  returns  the  USB - IrDA  class  descriptor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  usb_control_msg ( dev ,  usb_rcvctrlpipe ( dev , 0 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IU_REQ_GET_CLASS_DESC , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										USB_DIR_IN  |  USB_TYPE_CLASS  |  USB_RECIP_INTERFACE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										0 ,  intf - > altsetting - > desc . bInterfaceNumber ,  desc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										sizeof ( * desc ) ,  500 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s(), ret=%d \n " ,  __func__ ,  ret ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ret  <  sizeof ( * desc ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_WARNING ( " usb-irda: class_descriptor read %s (%d) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     ( ret < 0 )  ?  " failed "  :  " too short " ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( desc - > bDescriptorType  ! =  USB_DT_IRDA )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										IRDA_WARNING ( " usb-irda: bad class_descriptor type \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef IU_DUMP_CLASS_DESC 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_usb_dump_class_desc ( desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif	 /* IU_DUMP_CLASS_DESC */ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( desc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*********************** USB DEVICE CALLBACKS ***********************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Main  calls  from  the  USB  subsystem . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Mostly  registering  a  new  irda - usb  device  and  removing  it . . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  routine  is  called  by  the  USB  subsystem  for  each  new  device 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  in  the  system .  We  need  to  check  if  the  device  is  ours ,  and  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  this  case  start  handling  it . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  USB  layer  protect  us  from  reentrancy  ( via  BKL ) ,  so  we  don ' t  need 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  spinlock  in  there . . .  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_probe ( struct  usb_interface  * intf ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											  const  struct  usb_device_id  * id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  net_device  * net ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  usb_device  * dev  =  interface_to_usbdev ( intf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									struct  usb_host_interface  * interface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_class_desc  * irda_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret  =  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 		/* Driver instance index / Rx URB index */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : the probe make sure to call us only for devices that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  matches  the  list  of  dongle  ( top  of  the  file ) .  So ,  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  don ' t  need  to  check  if  the  dongle  is  really  ours . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_MESSAGE ( " IRDA-USB found at address %d, Vendor: %x, Product: %x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     dev - > devnum ,  le16_to_cpu ( dev - > descriptor . idVendor ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     le16_to_cpu ( dev - > descriptor . idProduct ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									net  =  alloc_irdadev ( sizeof ( * self ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! net )  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									SET_NETDEV_DEV ( net ,  & intf - > dev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-11-12 23:38:14 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self  =  netdev_priv ( net ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self - > netdev  =  net ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_init ( & self - > lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									init_timer ( & self - > rx_defer_timer ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > capability  =  id - > driver_info ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > needspatch  =  ( ( self - > capability  &  IUC_STIR421X )  ! =  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Create all of the needed urbs */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > capability  &  IUC_STIR421X )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > max_rx_urb  =  IU_SIGMATEL_MAX_RX_URBS ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > header_length  =  USB_IRDA_STIR421X_HEADER ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > max_rx_urb  =  IU_MAX_RX_URBS ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > header_length  =  USB_IRDA_HEADER ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > rx_urb  =  kcalloc ( self - > max_rx_urb ,  sizeof ( struct  urb  * ) , 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												GFP_KERNEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-03-07 02:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! self - > rx_urb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_free_net ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										self - > rx_urb [ i ]  =  usb_alloc_urb ( 0 ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! self - > rx_urb [ i ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  err_out_1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > tx_urb  =  usb_alloc_urb ( 0 ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > tx_urb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_out_1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > speed_urb  =  usb_alloc_urb ( 0 ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > speed_urb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_out_2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Is this really necessary? (no, except maybe for broken devices) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( usb_reset_configuration  ( dev )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err ( " reset_configuration failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Is this really necessary? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Note : some driver do hardcode the interface number, some others
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  specify  an  alternate ,  but  very  few  driver  do  like  this . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  usb_set_interface ( dev ,  intf - > altsetting - > desc . bInterfaceNumber ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " usb-irda: set interface %d result %d \n " ,  intf - > altsetting - > desc . bInterfaceNumber ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  ( ret )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - EPIPE : 		/* -EPIPE = -32 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Martin Diehl says if we get a -EPIPE we should
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  be  fine  and  we  don ' t  need  to  do  a  usb_clear_halt ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  -  Jean  II  */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											IRDA_DEBUG ( 0 ,  " %s(), Received -EPIPE, ignoring... \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											IRDA_DEBUG ( 0 ,  " %s(), Unknown error %d \n " ,  __func__ ,  ret ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											ret  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find our endpoints */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									interface  =  intf - > cur_altsetting ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( ! irda_usb_parse_endpoints ( self ,  interface - > endpoint , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     interface - > desc . bNumEndpoints ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										IRDA_ERROR ( " %s(), Bogus endpoints... \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										ret  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > usbdev  =  dev ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Find IrDA class descriptor */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_desc  =  irda_usb_find_class_desc ( intf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  - ENODEV ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! irda_desc ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( self - > needspatch )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  =  usb_control_msg  ( self - > usbdev ,  usb_sndctrlpipe  ( self - > usbdev ,  0 ) , 
							 
						 
					
						
							
								
									
										
										
										
											2006-05-06 18:34:10 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												       0x02 ,  0x40 ,  0 ,  0 ,  NULL ,  0 ,  500 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ret  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											IRDA_DEBUG  ( 0 ,  " usb_control_msg failed %d \n " ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											mdelay ( 10 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									self - > irda_desc  =   irda_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > present  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > netopen  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > usbintf  =  intf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Allocate the buffer for speed changes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Don't change this buffer size and allocation without doing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  some  heavy  and  complete  testing .  Don ' t  ask  why  : - ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Jean  II  */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > speed_buff  =  kzalloc ( IRDA_USB_SPEED_MTU ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self - > speed_buff ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										goto  err_out_3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									self - > tx_buff  =  kzalloc ( IRDA_SKB_MAX_MTU  +  self - > header_length , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												GFP_KERNEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! self - > tx_buff ) 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  err_out_4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									ret  =  irda_usb_open ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ret )  
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										goto  err_out_5 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_MESSAGE ( " IrDA: Registered device %s \n " ,  net - > name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_set_intfdata ( intf ,  self ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > needspatch )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Now we fetch and upload the firmware patch */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ret  =  stir421x_patch_device ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										self - > needspatch  =  ( ret  <  0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-11 20:56:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( self - > needspatch )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											IRDA_ERROR ( " STIR421X: Couldn't upload patch \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  err_out_6 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* replace IrDA class descriptor with what patched device is now reporting */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_desc  =  irda_usb_find_class_desc  ( self - > usbintf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! irda_desc )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ret  =  - ENODEV ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  err_out_6 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-08-10 15:25:40 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										kfree ( self - > irda_desc ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										self - > irda_desc  =  irda_desc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										irda_usb_init_qos ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								err_out_6 :  
						 
					
						
							
								
									
										
										
										
											2006-04-14 16:02:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unregister_netdev ( self - > netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-01-15 19:37:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								err_out_5 :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( self - > tx_buff ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								err_out_4 :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									kfree ( self - > speed_buff ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err_out_3 :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Free all urbs that we may have created */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_free_urb ( self - > speed_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err_out_2 :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_free_urb ( self - > tx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err_out_1 :  
						 
					
						
							
								
									
										
										
										
											2006-11-08 15:35:38 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usb_free_urb ( self - > rx_urb [ i ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2010-03-07 02:35:42 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( self - > rx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err_free_net :  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									free_netdev ( net ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								err_out :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  current  irda - usb  device  is  removed ,  the  USB  layer  tell  us 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  shut  it  down . . . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  One  of  the  constraints  is  that  when  we  exit  this  function , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  we  cannot  use  the  usb_device  no  more .  Gone .  Destroyed .  kfree ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Most  other  subsystem  allow  you  to  destroy  the  instance  at  a  time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  when  it ' s  convenient  to  you ,  to  postpone  it  to  a  later  date ,  but 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  not  the  USB  subsystem . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  So ,  we  must  make  bloody  sure  that  everything  gets  deactivated . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Jean  II 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  irda_usb_disconnect ( struct  usb_interface  * intf )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  flags ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  usb_get_intfdata ( intf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 1 ,  " %s() \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_set_intfdata ( intf ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Make sure that the Tx path is not executing. - Jean II */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock_irqsave ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Oups ! We are not there any more.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  This  will  stop / desactivate  the  Tx  path .  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > present  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Kill defered Rx URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									del_timer ( & self - > rx_defer_timer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* We need to have irq enabled to unlink the URBs. That's OK,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  at  this  point  the  Tx  path  is  gone  -  Jean  II  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock_irqrestore ( & self - > lock ,  flags ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Hum... Check if networking is still active (avoid races) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if ( ( self - > netopen )  | |  ( self - > irlap ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Accept no more transmissions */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*netif_device_detach(self->netdev);*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										netif_stop_queue ( self - > netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Stop all the receive URBs. Must be synchronous. */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											usb_kill_urb ( self - > rx_urb [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Cancel Tx and speed URB.
 
							 
						 
					
						
							
								
									
										
										
										
											2006-02-19 22:28:25 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 *  Make  sure  it ' s  synchronous  to  avoid  races .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										usb_kill_urb ( self - > tx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usb_kill_urb ( self - > speed_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Cleanup the device stuff */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									irda_usb_close ( self ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* No longer attached to USB bus */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > usbdev  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									self - > usbintf  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Clean up our urbs */ 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										usb_free_urb ( self - > rx_urb [ i ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( self - > rx_urb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Clean up Tx and speed URB */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_free_urb ( self - > tx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_free_urb ( self - > speed_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Free self and network device */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									free_netdev ( self - > netdev ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-07-30 17:20:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									IRDA_DEBUG ( 0 ,  " %s(), USB IrDA Disconnected \n " ,  __func__ ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-05-25 20:53:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef CONFIG_PM 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* USB suspend, so power off the transmitter/receiver */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_suspend ( struct  usb_interface  * intf ,  pm_message_t  message )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  usb_get_intfdata ( intf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_device_detach ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > tx_urb  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usb_kill_urb ( self - > tx_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( self - > speed_urb  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										usb_kill_urb ( self - > speed_urb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( self - > rx_urb [ i ]  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											usb_kill_urb ( self - > rx_urb [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Coming out of suspend, so reset hardware */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  irda_usb_resume ( struct  usb_interface  * intf )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  irda_usb_cb  * self  =  usb_get_intfdata ( intf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  self - > max_rx_urb ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( self - > rx_urb [ i ]  ! =  NULL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											usb_submit_urb ( self - > rx_urb [ i ] ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									netif_device_attach ( self - > netdev ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  USB  device  callbacks 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  usb_driver  irda_driver  =  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. name 		=  " irda-usb " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. probe 		=  irda_usb_probe , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. disconnect 	=  irda_usb_disconnect , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. id_table 	=  dongles , 
							 
						 
					
						
							
								
									
										
										
										
											2009-05-25 20:53:27 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef CONFIG_PM 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. suspend 	=  irda_usb_suspend , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									. resume 		=  irda_usb_resume , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/************************* MODULE CALLBACKS *************************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Deal  with  module  insertion / removal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Mostly  tell  USB  about  our  existence 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Module  insertion 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  __init  usb_irda_init ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int 	ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  usb_register ( & irda_driver ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ret  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									IRDA_MESSAGE ( " USB IrDA support registered \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								module_init ( usb_irda_init ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Module  removal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  void  __exit  usb_irda_cleanup ( void )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Deregister the driver and remove all pending instances */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									usb_deregister ( & irda_driver ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								module_exit ( usb_irda_cleanup ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*------------------------------------------------------------------*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Module  parameters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								module_param ( qos_mtt_bits ,  int ,  0 ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MODULE_PARM_DESC ( qos_mtt_bits ,  " Minimum Turn Time " ) ;  
						 
					
						
							
								
									
										
										
										
											2006-04-05 22:39:14 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								MODULE_AUTHOR ( " Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua> " ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								MODULE_DESCRIPTION ( " IrDA-USB Dongle Driver " ) ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								MODULE_LICENSE ( " GPL " ) ;