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

📄 hfc_usb.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * hfc_usb.c * * $Id: hfc_usb.c,v 4.36 2005/04/08 09:55:13 martinb1 Exp $ * * modular HiSax ISDN driver for Colognechip HFC-S USB chip * * Authors : Peter Sprenger  (sprenger@moving-bytes.de) *           Martin Bachem   (info@colognechip.com) * *           based on the first hfc_usb driver of *           Werner Cornelius (werner@isdn-development.de) * * 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, 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 02139, USA. * * See Version Histroy at the bottom of this file **/#include <linux/types.h>#include <linux/stddef.h>#include <linux/timer.h>#include <linux/config.h>#include <linux/init.h>#include <linux/module.h>#include <linux/kernel_stat.h>#include <linux/usb.h>#include <linux/kernel.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include "hisax.h"#include "hisax_if.h"#include "hfc_usb.h"static const char *hfcusb_revision =    "$Revision: 4.36 $ $Date: 2005/04/08 09:55:13 $ ";/* Hisax debug support* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG*/#ifdef CONFIG_HISAX_DEBUG#include <linux/moduleparam.h>#define __debug_variable hfc_debug#include "hisax_debug.h"static u_int debug;module_param(debug, uint, 0);static int hfc_debug;#endif/* private vendor specific data */typedef struct {	__u8 led_scheme;	// led display scheme	signed short led_bits[8];	// array of 8 possible LED bitmask settings	char *vend_name;	// device name} hfcsusb_vdata;/****************************************//* data defining the devices to be used *//****************************************/static struct usb_device_id hfcusb_idtab[] = {	{	 USB_DEVICE(0x0959, 0x2bd0),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_OFF, {4, 0, 2, 1},			   "ISDN USB TA (Cologne Chip HFC-S USB based)"}),	},	{	 USB_DEVICE(0x0675, 0x1688),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {1, 2, 0, 0},			   "DrayTek miniVigor 128 USB ISDN TA"}),	},	{	 USB_DEVICE(0x07b0, 0x0007),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {0x80, -64, -32, -16},			   "Billion tiny USB ISDN TA 128"}),	},	{	 USB_DEVICE(0x0742, 0x2008),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {4, 0, 2, 1},			   "Stollmann USB TA"}),	 },	{	 USB_DEVICE(0x0742, 0x2009),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {4, 0, 2, 1},			   "Aceex USB ISDN TA"}),	 },	{	 USB_DEVICE(0x0742, 0x200A),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {4, 0, 2, 1},			   "OEM USB ISDN TA"}),	 },	{	 USB_DEVICE(0x08e3, 0x0301),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {2, 0, 1, 4},			   "Olitec USB RNIS"}),	 },	{	 USB_DEVICE(0x07fa, 0x0846),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {0x80, -64, -32, -16},			   "Bewan Modem RNIS USB"}),	 },	{	 USB_DEVICE(0x07fa, 0x0847),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {0x80, -64, -32, -16},			   "Djinn Numeris USB"}),	 },	{	 USB_DEVICE(0x07b0, 0x0006),	 .driver_info = (unsigned long) &((hfcsusb_vdata)			  {LED_SCHEME1, {0x80, -64, -32, -16},			   "Twister ISDN TA"}),	 },	{ }};/***************************************************************//* structure defining input+output fifos (interrupt/bulk mode) *//***************************************************************/struct usb_fifo;		/* forward definition */typedef struct iso_urb_struct {	struct urb *purb;	__u8 buffer[ISO_BUFFER_SIZE];	/* buffer incoming/outgoing data */	struct usb_fifo *owner_fifo;	/* pointer to owner fifo */} iso_urb_struct;struct hfcusb_data;		/* forward definition */typedef struct usb_fifo {	int fifonum;		/* fifo index attached to this structure */	int active;		/* fifo is currently active */	struct hfcusb_data *hfc;	/* pointer to main structure */	int pipe;		/* address of endpoint */	__u8 usb_packet_maxlen;	/* maximum length for usb transfer */	unsigned int max_size;	/* maximum size of receive/send packet */	__u8 intervall;		/* interrupt interval */	struct sk_buff *skbuff;	/* actual used buffer */	struct urb *urb;	/* transfer structure for usb routines */	__u8 buffer[128];	/* buffer incoming/outgoing data */	int bit_line;		/* how much bits are in the fifo? */	volatile __u8 usb_transfer_mode;	/* switched between ISO and INT */	iso_urb_struct iso[2];	/* need two urbs to have one always for pending */	struct hisax_if *hif;	/* hisax interface */	int delete_flg;		/* only delete skbuff once */	int last_urblen;	/* remember length of last packet */} usb_fifo;/*********************************************//* structure holding all data for one device *//*********************************************/typedef struct hfcusb_data {	/* HiSax Interface for loadable Layer1 drivers */	struct hisax_d_if d_if;	/* see hisax_if.h */	struct hisax_b_if b_if[2];	/* see hisax_if.h */	int protocol;	struct usb_device *dev;	/* our device */	int if_used;		/* used interface number */	int alt_used;		/* used alternate config */	int ctrl_paksize;	/* control pipe packet size */	int ctrl_in_pipe, ctrl_out_pipe;	/* handles for control pipe */	int cfg_used;		/* configuration index used */	int vend_idx;		/* vendor found */	int b_mode[2];		/* B-channel mode */	int l1_activated;	/* layer 1 activated */	int disc_flag;		/* TRUE if device was disonnected to avoid some USB actions */	int packet_size, iso_packet_size;	/* control pipe background handling */	ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE];	/* buffer holding queued data */	volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt;	/* input/output pointer + count */	struct urb *ctrl_urb;	/* transfer structure for control channel */	struct usb_ctrlrequest ctrl_write;	/* buffer for control write request */	struct usb_ctrlrequest ctrl_read;	/* same for read request */	__u8 old_led_state, led_state, led_new_data, led_b_active;	volatile __u8 threshold_mask;	/* threshold actually reported */	volatile __u8 bch_enables;	/* or mask for sctrl_r and sctrl register values */	usb_fifo fifos[HFCUSB_NUM_FIFOS];	/* structure holding all fifo data */	volatile __u8 l1_state;	/* actual l1 state */	struct timer_list t3_timer;	/* timer 3 for activation/deactivation */	struct timer_list t4_timer;	/* timer 4 for activation/deactivation */} hfcusb_data;static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len,			     int finish);static inline const char *symbolic(struct hfcusb_symbolic_list list[], const int num){	int i;	for (i = 0; list[i].name != NULL; i++)		if (list[i].num == num)			return (list[i].name);	return "<unkown ERROR>";}/******************************************************//* start next background transfer for control channel *//******************************************************/static voidctrl_start_transfer(hfcusb_data * hfc){	if (hfc->ctrl_cnt) {		hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;		hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;		hfc->ctrl_urb->transfer_buffer = NULL;		hfc->ctrl_urb->transfer_buffer_length = 0;		hfc->ctrl_write.wIndex =		    hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;		hfc->ctrl_write.wValue =		    hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;		usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC);	/* start transfer */	}}				/* ctrl_start_transfer *//************************************//* queue a control transfer request *//* return 0 on success.             *//************************************/static intqueue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action){	ctrl_buft *buf;	if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)		return (1);	/* no space left */	buf = &hfc->ctrl_buff[hfc->ctrl_in_idx];	/* pointer to new index */	buf->hfc_reg = reg;	buf->reg_val = val;	buf->action = action;	if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)		hfc->ctrl_in_idx = 0;	/* pointer wrap */	if (++hfc->ctrl_cnt == 1)		ctrl_start_transfer(hfc);	return (0);}				/* queue_control_request */static intcontrol_action_handler(hfcusb_data * hfc, int reg, int val, int action){	if (!action)		return (1);	/* no action defined */	return (0);}/***************************************************************//* control completion routine handling background control cmds *//***************************************************************/static voidctrl_complete(struct urb *urb, struct pt_regs *regs){	hfcusb_data *hfc = (hfcusb_data *) urb->context;	ctrl_buft *buf;	urb->dev = hfc->dev;	if (hfc->ctrl_cnt) {		buf = &hfc->ctrl_buff[hfc->ctrl_out_idx];		control_action_handler(hfc, buf->hfc_reg, buf->reg_val,				       buf->action);		hfc->ctrl_cnt--;	/* decrement actual count */		if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)			hfc->ctrl_out_idx = 0;	/* pointer wrap */		ctrl_start_transfer(hfc);	/* start next transfer */	}}				/* ctrl_complete *//***************************************************//* write led data to auxport & invert if necessary *//***************************************************/static voidwrite_led(hfcusb_data * hfc, __u8 led_state){	if (led_state != hfc->old_led_state) {		hfc->old_led_state = led_state;		queue_control_request(hfc, HFCUSB_P_DATA, led_state, 1);	}}/**************************//* handle LED bits        *//**************************/static voidset_led_bit(hfcusb_data * hfc, signed short led_bits, int unset){	if (unset) {		if (led_bits < 0)			hfc->led_state |= abs(led_bits);		else			hfc->led_state &= ~led_bits;	} else {		if (led_bits < 0)			hfc->led_state &= ~abs(led_bits);		else			hfc->led_state |= led_bits;	}}/**************************//* handle LED requests    *//**************************/static voidhandle_led(hfcusb_data * hfc, int event){	hfcsusb_vdata *driver_info =	    (hfcsusb_vdata *) hfcusb_idtab[hfc->vend_idx].driver_info;	/* if no scheme -> no LED action */	if (driver_info->led_scheme == LED_OFF)		return;	switch (event) {		case LED_POWER_ON:			set_led_bit(hfc, driver_info->led_bits[0],				    0);			set_led_bit(hfc, driver_info->led_bits[1],				    1);			set_led_bit(hfc, driver_info->led_bits[2],				    1);			set_led_bit(hfc, driver_info->led_bits[3],				    1);			break;		case LED_POWER_OFF:	/* no Power off handling */			break;		case LED_S0_ON:			set_led_bit(hfc, driver_info->led_bits[1],				    0);			break;		case LED_S0_OFF:			set_led_bit(hfc, driver_info->led_bits[1],				    1);			break;		case LED_B1_ON:			set_led_bit(hfc, driver_info->led_bits[2],				    0);			break;		case LED_B1_OFF:			set_led_bit(hfc, driver_info->led_bits[2],				    1);			break;		case LED_B2_ON:			set_led_bit(hfc, driver_info->led_bits[3],				    0);			break;		case LED_B2_OFF:			set_led_bit(hfc, driver_info->led_bits[3],				    1);			break;	}	write_led(hfc, hfc->led_state);}/********************************//* called when timer t3 expires *//********************************/static voidl1_timer_expire_t3(hfcusb_data * hfc){	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,			   NULL);#ifdef CONFIG_HISAX_DEBUG	DBG(ISDN_DBG,	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");#endif	hfc->l1_activated = FALSE;	handle_led(hfc, LED_S0_OFF);	/* deactivate : */	queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);	queue_control_request(hfc, HFCUSB_STATES, 3, 1);}/********************************//* called when timer t4 expires *//********************************/static voidl1_timer_expire_t4(hfcusb_data * hfc){	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,			   NULL);#ifdef CONFIG_HISAX_DEBUG	DBG(ISDN_DBG,	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");#endif	hfc->l1_activated = FALSE;	handle_led(hfc, LED_S0_OFF);}/*****************************//* handle S0 state changes   *//*****************************/static voidstate_handler(hfcusb_data * hfc, __u8 state){	__u8 old_state;	old_state = hfc->l1_state;	if (state == old_state || state < 1 || state > 8)		return;#ifdef CONFIG_HISAX_DEBUG	DBG(ISDN_DBG, "HFC-S USB: new S0 state:%d old_state:%d", state,	    old_state);#endif	if (state < 4 || state == 7 || state == 8) {		if (timer_pending(&hfc->t3_timer))			del_timer(&hfc->t3_timer);#ifdef CONFIG_HISAX_DEBUG		DBG(ISDN_DBG, "HFC-S USB: T3 deactivated");#endif	}

⌨️ 快捷键说明

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