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

📄 capidrv.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct ncci_datahandle_queue *n, **pp;	n = (struct ncci_datahandle_queue *)		kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);	if (!n) {	   printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");	   return -1;	}	n->next = 0;	n->datahandle = datahandle;	n->len = len;	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;	*pp = n;	return 0;}static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle){	struct ncci_datahandle_queue **pp, *p;	int len;	for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) { 		if ((*pp)->datahandle == datahandle) {			p = *pp;			len = p->len;			*pp = (*pp)->next;		        kfree(p);			return len;		}	}	return -1;}/* -------- convert and send capi message ---------------------------- */static void send_message(capidrv_contr * card, _cmsg * cmsg){	struct sk_buff *skb;	size_t len;	capi_cmsg2message(cmsg, cmsg->buf);	len = CAPIMSG_LEN(cmsg->buf);	skb = alloc_skb(len, GFP_ATOMIC);	memcpy(skb_put(skb, len), cmsg->buf, len);	(*capifuncs->capi_put_message) (global.appid, skb);	global.nsentctlpkt++;}/* -------- state machine -------------------------------------------- */struct listenstatechange {	int actstate;	int nextstate;	int event;};static struct listenstatechange listentable[] ={  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},  {},};static void listen_change_state(capidrv_contr * card, int event){	struct listenstatechange *p = listentable;	while (p->event) {		if (card->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",				       card->contrnr, card->state, p->nextstate);			card->state = p->nextstate;			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",	       card->contrnr, card->state, event);}/* ------------------------------------------------------------------ */static void p0(capidrv_contr * card, capidrv_plci * plci){	isdn_ctrl cmd;	card->bchans[plci->chan].contr = 0;	cmd.command = ISDN_STAT_DHUP;	cmd.driver = card->myid;	cmd.arg = plci->chan;	card->interface.statcallb(&cmd);	free_plci(card, plci);}/* ------------------------------------------------------------------ */struct plcistatechange {	int actstate;	int nextstate;	int event;	void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);};static struct plcistatechange plcitable[] ={  /* P-0 */  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},  /* P-0.1 */  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},  /* P-1 */  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-ACT */  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},  /* P-2 */  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},  /* P-3 */  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-4 */  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-5 */  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},  /* P-6 */  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},  /* P-0.Res */  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},  /* P-RES */  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},  /* P-HELD */  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},  {},};static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event){	struct plcistatechange *p = plcitable;	while (p->event) {		if (plci->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",				  card->contrnr, plci->plci, plci->state, p->nextstate);			plci->state = p->nextstate;			if (p->changefunc)				p->changefunc(card, plci);			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",	       card->contrnr, plci->plci, plci->state, event);}/* ------------------------------------------------------------------ */static _cmsg cmsg;static void n0(capidrv_contr * card, capidrv_ncci * ncci){	isdn_ctrl cmd;	capi_fill_DISCONNECT_REQ(&cmsg,				 global.appid,				 card->msgid++,				 ncci->plcip->plci,				 0,	/* BChannelinformation */				 0,	/* Keypadfacility */				 0,	/* Useruserdata */   /* $$$$ */				 0	/* Facilitydataarray */	);	send_message(card, &cmsg);	plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);	cmd.command = ISDN_STAT_BHUP;	cmd.driver = card->myid;	cmd.arg = ncci->chan;	card->interface.statcallb(&cmd);	free_ncci(card, ncci);}/* ------------------------------------------------------------------ */struct nccistatechange {	int actstate;	int nextstate;	int event;	void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);};static struct nccistatechange nccitable[] ={  /* N-0 */  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},  /* N-0.1 */  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},  /* N-1 */  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-2 */  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-ACT */  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-3 */  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},  /* N-4 */  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},  /* N-5 */  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},  {},};static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event){	struct nccistatechange *p = nccitable;	while (p->event) {		if (ncci->state == p->actstate && p->event == event) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",				  card->contrnr, ncci->ncci, ncci->state, p->nextstate);			if (p->nextstate == ST_NCCI_PREVIOUS) {				ncci->state = ncci->oldstate;				ncci->oldstate = p->actstate;			} else {				ncci->oldstate = p->actstate;				ncci->state = p->nextstate;			}			if (p->changefunc)				p->changefunc(card, ncci);			return;		}		p++;	}	printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",	       card->contrnr, ncci->ncci, ncci->state, event);}/* ------------------------------------------------------------------- */static inline int new_bchan(capidrv_contr * card){	int i;	for (i = 0; i < card->nbchan; i++) {		if (card->bchans[i].plcip == 0) {			card->bchans[i].disconnecting = 0;			return i;		}	}	return -1;}/* ------------------------------------------------------------------- */static void handle_controller(_cmsg * cmsg){	capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);	if (!card) {		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),		       cmsg->adr.adrController & 0x7f);		return;	}	switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {	case CAPI_LISTEN_CONF:	/* Controller */		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",			       card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);		if (cmsg->Info) {			listen_change_state(card, EV_LISTEN_CONF_ERROR);		} else if (card->cipmask == 0) {			listen_change_state(card, EV_LISTEN_CONF_EMPTY);		} else {			listen_change_state(card, EV_LISTEN_CONF_OK);		}		break;	case CAPI_MANUFACTURER_IND:	/* Controller */		if (   cmsg->ManuID == 0x214D5641		    && cmsg->Class == 0		    && cmsg->Function == 1) {		   __u8  *data = cmsg->ManuData+3;		   __u16  len = cmsg->ManuData[0];		   __u16 layer;		   int direction;		   if (len == 255) {		      len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));		      data += 2;		   }		   len -= 2;		   layer = ((*(data-1)) << 8) | *(data-2);		   if (layer & 0x300)			direction = (layer & 0x200) ? 0 : 1;		   else direction = (layer & 0x800) ? 0 : 1;		   if (layer & 0x0C00) {		   	if ((layer & 0xff) == 0x80) {		           handle_dtrace_data(card, direction, 1, data, len);		           break;		   	}		   } else if ((layer & 0xff) < 0x80) {		      handle_dtrace_data(card, direction, 0, data, len);		      break;		   }	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",                        card->contrnr, 			capi_cmd2str(cmsg->Command, cmsg->Subcommand),			cmsg->adr.adrController, layer);                   break;		}		goto ignored;	case CAPI_MANUFACTURER_CONF:	/* Controller */		if (cmsg->ManuID == 0x214D5641) {		   char *s = 0;		   switch (cmsg->Class) {		      case 0: break;		      case 1: s = "unknown class"; break;		      case 2: s = "unknown function"; break;		      default: s = "unkown error"; break;		   }		   if (s)	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",			card->contrnr,			capi_cmd2str(cmsg->Command, cmsg->Subcommand),			cmsg->adr.adrController,			cmsg->Function, s);		   break;		}		goto ignored;	case CAPI_FACILITY_IND:	/* Controller/plci/ncci */		goto ignored;	case CAPI_FACILITY_CONF:	/* Controller/plci/ncci */		goto ignored;	case CAPI_INFO_IND:	/* Controller/plci */		goto ignored;	case CAPI_INFO_CONF:	/* Controller/plci */		goto ignored;	default:		printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",		       card->contrnr,		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),		       cmsg->adr.adrController);	}	return;      ignored:	printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",	       card->contrnr,	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),	       cmsg->adr.adrController);}static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg){	capidrv_plci *plcip;	capidrv_bchan *bchan;	isdn_ctrl cmd;	int chan;	if ((chan = new_bchan(card)) == -1) {		printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);		return;	}	bchan = &card->bchans[chan];	if ((plcip = new_plci(card, chan)) == 0) {		printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);		return;	}	bchan->incoming = 1;	plcip->plci = cmsg->adr.adrPLCI;	plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);	cmd.command = ISDN_STAT_ICALL;	cmd.driver = card->myid;	cmd.arg = chan;	memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));	strncpy(cmd.parm.setup.phone,	        cmsg->CallingPartyNumber + 3,		cmsg->CallingPartyNumber[0] - 2);	strncpy(cmd.parm.setup.eazmsn,	        cmsg->CalledPartyNumber + 2,		cmsg->CalledPartyNumber[0] - 1);	cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);	cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);	cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];	cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];	printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", 			card->contrnr,			cmd.parm.setup.phone,			cmd.parm.setup.si1,			cmd.parm.setup.si2,			cmd.parm.setup.eazmsn);	if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {		printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n", 			card->contrnr,			cmd.parm.setup.si2);		cmd.parm.setup.si2 = 0;	}	switch (card->interface.statcallb(&cmd)) {	case 0:	case 3:		/* No device matching this call.		 * and isdn_common.c has send a HANGUP command		 * which is ignored in state ST_PLCI_INCOMING,		 * so we send RESP to ignore the call		 */		capi_cmsg_answer(cmsg);		cmsg->Reject = 1;	/* ignore */		send_message(card, cmsg);		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);		printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",			card->contrnr,			cmd.parm.setup.phone,			cmd.parm.setup.si1,			cmd.parm.setup.si2,			cmd.parm.setup.eazmsn);		break;	case 1:		/* At least one device matching this call (RING on ttyI)		 * HL-driver may send ALERTING on the D-channel in this		 * case.		 * really means: RING on ttyI or a net interface		 * accepted this call already.		 *		 * If the call was accepted, state has already changed,		 * and CONNECT_RESP already sent.		 */		if (plcip->state == ST_PLCI_INCOMING) {			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",				card->contrnr,				cmd.parm.setup.phone,				cmd.parm.setup.si1,

⌨️ 快捷键说明

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