⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hfc_usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
}				/* rx_iso_complete *//*****************************************************//* collect data from interrupt or isochron in        *//*****************************************************/static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish){	hfcusb_data *hfc = fifo->hfc;	int transp_mode,fifon;	fifon=fifo->fifonum;	transp_mode=0;	if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;	//printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);	if(!fifo->skbuff)	{		// allocate sk buffer		fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);		if(!fifo->skbuff)		{			printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);			return;		}			}	if(len && fifo->skbuff->len+len<fifo->max_size)	{		memcpy(skb_put(fifo->skbuff,len),data,len);	}	else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);	// give transparent data up, when 128 byte are available	if(transp_mode && fifo->skbuff->len>=128)	{		fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);		fifo->skbuff = NULL;  // buffer was freed from upper layer		return;	}	// we have a complete hdlc packet	if(finish)	{		if(!fifo->skbuff->data[fifo->skbuff->len-1])		{			skb_trim(fifo->skbuff,fifo->skbuff->len-3);  // remove CRC & status			//printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);			if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);			else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);			fifo->skbuff = NULL;  // buffer was freed from upper layer		}		else		{			printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);			skb_trim(fifo->skbuff,0);  // clear whole buffer		}	}	// LED flashing only in HDLC mode	if(!transp_mode)	{		if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);		if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);	}}/***********************************************//* receive completion routine for all rx fifos *//***********************************************/static void rx_complete(struct urb *urb, struct pt_regs *regs){	int len;	__u8 *buf;	usb_fifo *fifo = (usb_fifo *) urb->context;	/* pointer to our fifo */	hfcusb_data *hfc = fifo->hfc;	urb->dev = hfc->dev;	/* security init */	if((!fifo->active) || (urb->status)) {#ifdef VERBOSE_USB_DEBUG		printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);#endif		fifo->urb->interval = 0;	/* cancel automatic rescheduling */		if(fifo->skbuff) {			dev_kfree_skb_any(fifo->skbuff);			fifo->skbuff = NULL;		}		return;	}	len=urb->actual_length;	buf=fifo->buffer;	if(fifo->last_urblen!=fifo->usb_packet_maxlen) {		// the threshold mask is in the 2nd status byte		hfc->threshold_mask=buf[1];		// the S0 state is in the upper half of the 1st status byte		state_handler(hfc,buf[0] >> 4);		// if we have more than the 2 status bytes -> collect data		if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);	} else		collect_rx_frame(fifo,buf,urb->actual_length,0);	fifo->last_urblen=urb->actual_length;}	/* rx_complete *//***************************************************//* start the interrupt transfer for the given fifo *//***************************************************/static void start_int_fifo(usb_fifo * fifo){	int errcode;#ifdef VERBOSE_USB_DEBUG	printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);#endif	if (!fifo->urb) {		fifo->urb = usb_alloc_urb(0, GFP_KERNEL);		if (!fifo->urb)			return;	}	usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,				 fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);	fifo->active = 1;		/* must be marked active */	errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);	if(errcode)	{		printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n",   errcode);		fifo->active = 0;		fifo->skbuff = NULL;	}} /* start_int_fifo *//*****************************//* set the B-channel mode    *//*****************************/static void set_hfcmode(hfcusb_data *hfc,int channel,int mode){	__u8 val,idx_table[2]={0,2};#ifdef VERBOSE_ISDN_DEBUG  printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);#endif	hfc->b_mode[channel]=mode;	// setup CON_HDLC	val=0;	if(mode!=L1_MODE_NULL) val=8;    // enable fifo?	if(mode==L1_MODE_TRANS) val|=2;  // set transparent bit	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1);  // reset fifo	val=0x40;	if(hfc->b_mode[0]) val|=1;	if(hfc->b_mode[1]) val|=2;	queue_control_request(hfc,HFCUSB_SCTRL,val,1);	val=0;	if(hfc->b_mode[0]) val|=1;	if(hfc->b_mode[1]) val|=2;	queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);	if(mode==L1_MODE_NULL)	{		if(channel) handle_led(hfc,LED_B2_OFF);		else handle_led(hfc,LED_B1_OFF);	}	else	{		if(channel) handle_led(hfc,LED_B2_ON);		else handle_led(hfc,LED_B1_ON);	}}/*   --------------------------------------------------------------------------------------   from here : hisax_if callback routines :     - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {   l1 to l2 routines :     - static void hfc_usb_l1l2(hfcusb_data * hfc)*/void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg){    usb_fifo *fifo = my_hisax_if->priv;	hfcusb_data *hfc = fifo->hfc;    switch (pr) {		case PH_ACTIVATE | REQUEST:				if(fifo->fifonum==HFCUSB_D_TX)				{#ifdef VERBOSE_ISDN_DEBUG					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");#endif					queue_control_request(hfc, HFCUSB_STATES,0x60,1);	/* make activation */					hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;					if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);				}				else				{#ifdef VERBOSE_ISDN_DEBUG					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");#endif					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);					fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);				}                break;        case PH_DEACTIVATE | REQUEST:				if(fifo->fifonum==HFCUSB_D_TX)				{#ifdef VERBOSE_ISDN_DEBUG					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");#endif					printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");				}				else				{#ifdef VERBOSE_ISDN_DEBUG					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");#endif					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);					fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);				}                break;		case PH_DATA | REQUEST:				if(fifo->skbuff && fifo->delete_flg)				{					dev_kfree_skb_any(fifo->skbuff);					//printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);					fifo->skbuff = NULL;					fifo->delete_flg=FALSE;				}				fifo->skbuff=arg; // we have a new buffer				//if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");				//else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");                break;        default:                printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);                break;    }}// valid configurations#define CNF_4INT3ISO  1      // 4 INT IN, 3 ISO OUT#define CNF_3INT3ISO  2      // 3 INT IN, 3 ISO OUT#define CNF_4ISO3ISO  3      // 4 ISO IN, 3 ISO OUT#define CNF_3ISO3ISO  4 	 // 3 ISO IN, 3 ISO OUT/*   --------------------------------------------------------------------------------------   From here on USB initialization and deactivation related routines are implemented :   - hfc_usb_init :      is the main Entry Point for the USB Subsystem when the device get plugged      in. This function calls usb_register with usb_driver as parameter.      Here, further entry points for probing (hfc_usb_probe) and disconnecting      the device (hfc_usb_disconnect) are published, as the id_table   - hfc_usb_probe      this function is called by the usb subsystem, and steps through the alternate      settings of the currently plugged in device to detect all Endpoints needed to      run an ISDN TA.      Needed EndPoints are      3 (+1) IntIn EndPoints   (D-in,  E-in, B1-in, B2-in, (E-in)) or      3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints      The currently used transfer mode of on the Out-Endpoints will be stored in      hfc->usb_transfer_mode and is either USB_INT or USB_ISO      When a valid alternate setting could be found, the usb_init (see blow)      function is called   - usb_init      Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive      Data to/from the several EndPoints are initialized:       The E- and D-Channel Int-In chain gets started       The IsoChain for the Iso-Out traffic get started   - hfc_usb_disconnect      this function is called by the usb subsystem and has to free all resources      and stop all usb traffic to allow a proper hotplugging disconnect.*//***************************************************************************//* usb_init is called once when a new matching device is detected to setup *//* main parameters. It registers the driver at the main hisax module.       *//* on success 0 is returned.                                               *//***************************************************************************/static int usb_init(hfcusb_data * hfc){	usb_fifo *fifo;	int i, err;	u_char b;	struct hisax_b_if *p_b_if[2];		/* check the chip id */	printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");	if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {		printk(KERN_INFO "HFC-USB: cannot read chip id\n");		return(1); 	}	printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);	if (b != HFCUSB_CHIPID) {		printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);		return(1);	}	/* first set the needed config, interface and alternate */	printk(KERN_INFO "usb_init 1\n");//	usb_set_configuration(hfc->dev, 1);	printk(KERN_INFO "usb_init 2\n");	err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);	printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);	/* now we initialize the chip */	write_usb(hfc, HFCUSB_CIRM, 8);	    // do reset	write_usb(hfc, HFCUSB_CIRM, 0x10);	// aux = output, reset off	// set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers	write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));	// set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers	write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);	/* enable PCM/GCI master mode */	write_usb(hfc, HFCUSB_MST_MODE1, 0);	/* set default values */	write_usb(hfc, HFCUSB_MST_MODE0, 1);	/* enable master mode */	/* init the fifos */	write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));	fifo = hfc->fifos;	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)	{		write_usb(hfc, HFCUSB_FIFO, i);	/* select the desired fifo */		fifo[i].skbuff = NULL;	/* init buffer pointer */		fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;		fifo[i].last_urblen=0;		write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2));	    // set 2 bit for D- & E-channel		write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08));	// rx hdlc, enable IFF for D-channel		write_usb(hfc, HFCUSB_INC_RES_F, 2);	/* reset the fifo */	}	write_usb(hfc, HFCUSB_CLKDEL, 0x0f);	 /* clock delay value */	write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */	write_usb(hfc, HFCUSB_STATES, 3);	     /* enable state machine */	write_usb(hfc, HFCUSB_SCTRL_R, 0);	     /* disable both B receivers */	write_usb(hfc, HFCUSB_SCTRL, 0x40);	     /* disable B transmitters + capacitive mode */	// set both B-channel to not connected	hfc->b_mode[0]=L1_MODE_NULL;	hfc->b_mode[1]=L1_MODE_NULL;	hfc->l1_activated=FALSE;	hfc->led_state=0;	hfc->led_new_data=0;	/* init the t3 timer */	init_timer(&hfc->t3_timer);	hfc->t3_timer.data = (long) hfc;	hfc->t3_timer.function = (void *) l1_timer_expire_t3;	/* init the t4 timer */	init_timer(&hfc->t4_timer);	hfc->t4_timer.data = (long) hfc;	hfc->t4_timer.function = (void *) l1_timer_expire_t4;	/* init the led timer */	init_timer(&hfc->led_timer);	hfc->led_timer.data = (long) hfc;	hfc->led_timer.function = (void *) led_timer;	// trigger 4 hz led timer	hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;	if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);	// init the background machinery for control requests	hfc->ctrl_read.bRequestType = 0xc0;	hfc->ctrl_read.bRequest = 1;	hfc->ctrl_read.wLength = 1;	hfc->ctrl_write.bRequestType = 0x40;	hfc->ctrl_write.bRequest = 0;	hfc->ctrl_write.wLength = 0;	usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);						/* Init All Fifos */	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)	{		hfc->fifos[i].iso[0].purb = NULL;		hfc->fifos[i].iso[1].purb = NULL;		hfc->fifos[i].active = 0;	}	// register like Germaschewski :	hfc->d_if.owner = THIS_MODULE;	hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];	hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;	for (i=0; i<2; i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -