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

📄 capidrv.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				       0,	/* B3configuration */				       0,	/* ConnectedNumber */				       0,	/* ConnectedSubaddress */				       0,	/* LLC */				       0,	/* BChannelinformation */				       0,	/* Keypadfacility */				       0,	/* Useruserdata */				       0	/* Facilitydataarray */		);		capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);		plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);		send_message(card, &cmdcmsg);		return 0;	case ISDN_CMD_ACCEPTB:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",			       card->contrnr,			       c->arg);		return -ENOSYS;	case ISDN_CMD_HANGUP:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",			       card->contrnr,			       c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		if (bchan->disconnecting) {			if (debugmode)				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",				       card->contrnr,				       c->arg);			return 0;		}		if (bchan->nccip) {			bchan->disconnecting = 1;			capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,						    global.appid,						    card->msgid++,						    bchan->nccip->ncci,						    0	/* NCPI */			);			ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);			send_message(card, &cmdcmsg);		} else if (bchan->plcip) {			bchan->disconnecting = 1;			if (bchan->plcip->state == ST_PLCI_INCOMING) {				/* just ignore, we a called from isdn_status_callback(),				 * which will return 0 or 2, this is handled by the				 * CONNECT_IND handler				 */			} else {				capi_fill_DISCONNECT_REQ(&cmdcmsg,							 global.appid,							 card->msgid++,						      bchan->plcip->plci,							 0,	/* BChannelinformation */							 0,	/* Keypadfacility */							 0,	/* Useruserdata */							 0	/* Facilitydataarray */				);				plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);				send_message(card, &cmdcmsg);			}		}/* ready */	case ISDN_CMD_SETL2:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l2 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETL3:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",			       card->contrnr,			       (c->arg & 0xff), (c->arg >> 8));		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];		bchan->l3 = (c->arg >> 8);		return 0;	case ISDN_CMD_SETEAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",			       card->contrnr,			       c->parm.num, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);		return 0;	case ISDN_CMD_CLREAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",					card->contrnr, c->arg);		bchan = &card->bchans[c->arg % card->nbchan];		bchan->msn[0] = 0;		return 0;	case ISDN_CMD_LOCK:		if (debugmode > 1)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);		MOD_INC_USE_COUNT;		break;	case ISDN_CMD_UNLOCK:		if (debugmode > 1)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",					card->contrnr, c->arg);		MOD_DEC_USE_COUNT;		break;/* never called */	case ISDN_CMD_GETL2:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETL3:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETEAZ:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_SETSIL:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",					card->contrnr);		return -ENODEV;	case ISDN_CMD_GETSIL:		if (debugmode)			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",					card->contrnr);		return -ENODEV;	default:		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",					card->contrnr, c->command);		return -EINVAL;	}	return 0;}static int if_command(isdn_ctrl * c){	capidrv_contr *card = findcontrbydriverid(c->driver);	if (card)		return capidrv_command(c, card);	printk(KERN_ERR	     "capidrv-%d: if_command %d called with invalid driverId %d!\n",	       card->contrnr, c->command, c->driver);	return -ENODEV;}static _cmsg sendcmsg;static int if_sendbuf(int id, int channel, struct sk_buff *skb){	capidrv_contr *card = findcontrbydriverid(id);	capidrv_bchan *bchan;	capidrv_ncci *nccip;	int len = skb->len;	size_t msglen;	__u16 errcode;	if (!card) {		printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",		       card->contrnr, id);		return 0;	}	bchan = &card->bchans[channel % card->nbchan];	nccip = bchan->nccip;	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {		printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",		       card->contrnr, card->name, channel);		return 0;	}	capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++,			      nccip->ncci,	/* adr */			      (__u32) skb->data,	/* Data */			      skb->len,		/* DataLength */			      nccip->datahandle++,	/* DataHandle */			      0	/* Flags */	    );	capi_cmsg2message(&sendcmsg, sendcmsg.buf);	msglen = CAPIMSG_LEN(sendcmsg.buf);	if (skb_headroom(skb) < msglen) {		struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);		if (!nskb) {			printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",					card->contrnr);			return 0;		}#if 0		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom\n",		       card->contrnr, skb_headroom(skb));#endif                SET_SKB_FREE(nskb);		memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);		memcpy(skb_put(nskb, skb->len), skb->data, skb->len);		errcode = (*capifuncs->capi_put_message) (global.appid, nskb);		switch (errcode) {		case CAPI_NOERROR:			dev_kfree_skb(skb, FREE_WRITE);			return len;		case CAPI_SENDQUEUEFULL:			dev_kfree_skb(nskb, FREE_WRITE);			return 0;		default:			return -1;		}	} else {		memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);		errcode = (*capifuncs->capi_put_message) (global.appid, skb);		switch (errcode) {		case CAPI_NOERROR:			return len;		case CAPI_SENDQUEUEFULL:			return 0;		default:			return -1;		}	}}static int if_readstat(__u8 *buf, int len, int user, int id, int channel){	capidrv_contr *card = findcontrbydriverid(id);	int count;	__u8 *p;	if (!card) {		printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",		       card->contrnr, id);		return -ENODEV;	}	for (p=buf, count=0; count < len; p++, count++) {	        if (user)	                put_user(*card->q931_read++, p);	        else	                *p = *card->q931_read++;	        if (card->q931_read > card->q931_end)	                card->q931_read = card->q931_buf;	}	return count;}static void enable_dchannel_trace(capidrv_contr *card){        __u8 manufacturer[CAPI_MANUFACTURER_LEN];        capi_version version;	__u16 contr = card->contrnr;	__u16 errcode;	__u16 avmversion[3];        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);        if (errcode != CAPI_NOERROR) {	   printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",			card->name, errcode);	   return;	}	if (strstr(manufacturer, "AVM") == 0) {	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible\n",			card->name);	   return;	}        errcode = (*capifuncs->capi_get_version)(contr, &version);        if (errcode != CAPI_NOERROR) {	   printk(KERN_ERR "%s: can't get version (0x%x)\n",			card->name, errcode);	   return;	}	avmversion[0] = (version.majormanuversion >> 4) & 0x0f;	avmversion[1] = (version.majormanuversion << 4) & 0xf0;	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;	avmversion[2] |= version.minormanuversion & 0x0f;        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {		printk(KERN_INFO "%s: D2 trace enabled\n", card->name);		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,					   card->msgid++,					   contr,					   0x214D5641,  /* ManuID */					   0,           /* Class */					   1,           /* Function */					   (_cstruct)"\004\200\014\000\000");	} else {		printk(KERN_INFO "%s: D3 trace enabled\n", card->name);		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,					   card->msgid++,					   contr,					   0x214D5641,  /* ManuID */					   0,           /* Class */					   1,           /* Function */					   (_cstruct)"\004\002\003\000\000");	}	send_message(card, &cmdcmsg);}static int capidrv_addcontr(__u16 contr, struct capi_profile *profp){	capidrv_contr *card;	isdn_ctrl cmd;	char id[20];	int i;	sprintf(id, "capidrv-%d", contr);	if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {		printk(KERN_WARNING		 "capidrv: (%s) Could not allocate contr-struct.\n", id);		return -1;	}	memset(card, 0, sizeof(capidrv_contr));	strcpy(card->name, id);	card->contrnr = contr;	card->nbchan = profp->nbchannel;	card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);	if (!card->bchans) {		printk(KERN_WARNING		"capidrv: (%s) Could not allocate bchan-structs.\n", id);		kfree(card);		return -1;	}	card->interface.channels = profp->nbchannel;	card->interface.maxbufsize = 2048;	card->interface.command = if_command;	card->interface.writebuf_skb = if_sendbuf;	card->interface.writecmd = 0;	card->interface.readstat = if_readstat;	card->interface.features = ISDN_FEATURE_L2_X75I |	    ISDN_FEATURE_L2_X75UI |	    ISDN_FEATURE_L2_X75BUI |	    ISDN_FEATURE_L2_HDLC |	    ISDN_FEATURE_L2_TRANS |	    ISDN_FEATURE_L3_TRANS |	    ISDN_FEATURE_P_UNKNOWN;	card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */	strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);	card->next = global.contr_list;	global.contr_list = card;	global.ncontr++;	card->q931_read = card->q931_buf;	card->q931_write = card->q931_buf;	card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;	if (!register_isdn(&card->interface)) {		global.contr_list = global.contr_list->next;		printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);		kfree(card->bchans);		kfree(card);		return -1;	}	card->myid = card->interface.channels;	memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);	for (i = 0; i < card->nbchan; i++) {		card->bchans[i].contr = card;	}	cmd.driver = card->myid;	cmd.command = ISDN_STAT_RUN;	card->interface.statcallb(&cmd);	card->cipmask = 0x1FFF03FF;	/* any */	card->cipmask2 = 0;	capi_fill_LISTEN_REQ(&cmdcmsg, global.appid,			     card->msgid++,			     contr,	/* controller */			     1 << 6,	/* Infomask */			     card->cipmask,			     card->cipmask2,			     0, 0);	send_message(card, &cmdcmsg);	listen_change_state(card, EV_LISTEN_REQ);	printk(KERN_INFO "%s: now up (%d B channels)\n",		card->name, card->nbchan);        if (card->nbchan == 2)  /* no T1 */        	enable_dchannel_trace(card);	return 0;}static int capidrv_delcontr(__u16 contr){	capidrv_contr **pp, *card;	isdn_ctrl cmd;	int i;	for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {		if ((*pp)->contrnr == contr)			break;	}	if (!*pp) {		printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);		return -1;	}	card = *pp;	*pp = (*pp)->next;	global.ncontr--;	for (i = 0; i < card->nbchan; i++) {		if (card->bchans[i].nccip)			free_ncci(card, card->bchans[i].nccip);		if (card->bchans[i].plcip)			free_plci(card, card->bchans[i].plcip);		if (card->plci_list)			printk(KERN_ERR "capidrv: bug in free_plci()\n");	}	kfree(card->bchans);	cmd.command = ISDN_STAT_UNLOAD;	cmd.driver = card->myid;	card->interface.statcallb(&cmd);	printk(KERN_INFO "%s: now down.\n", card->name);	kfree(card);	return 0;}static void lower_callback(unsigned int cmd, __u16 contr, void *data){	switch (cmd) {	case KCI_CONTRUP:		(void) capidrv_addcontr(contr, (capi_profile *) data);		break;	case KCI_CONTRDOWN:		(void) capidrv_delcontr(contr);		break;	}}static struct capi_interface_user cuser = {	"capidrv",	lower_callback};#ifdef MODULE#define capidrv_init init_module#endifint capidrv_init(void){	struct capi_register_params rparam;	capi_profile profile;	char rev[10];	char *p;	__u32 ncontr, contr;	__u16 errcode;	capifuncs = attach_capi_interface(&cuser);	if (!capifuncs)		return -EIO;#ifndef HAS_NEW_SYMTAB	/* No symbols to export, hide all symbols */	register_symtab(NULL);#endif	if ((p = strchr(revision, ':'))) {		strcpy(rev, p + 1);		p = strchr(rev, '$');		*p = 0;	} else		strcpy(rev, " ??? ");	rparam.level3cnt = -2;  /* number of bchannels twice */	rparam.datablkcnt = 16;	rparam.datablklen = 2048;	errcode = (*capifuncs->capi_register) (&rparam, &global.appid);	if (errcode) {		detach_capi_interface(&cuser);		return -EIO;	}	errcode = (*capifuncs->capi_get_profile) (0, &profile);	if (errcode != CAPI_NOERROR) {		(void) (*capifuncs->capi_release) (global.appid);		detach_capi_interface(&cuser);		return -EIO;	}	(void) (*capifuncs->capi_set_signal) (global.appid, capidrv_signal, 0);	ncontr = profile.ncontroller;	for (contr = 1; contr <= ncontr; contr++) {		errcode = (*capifuncs->capi_get_profile) (contr, &profile);		if (errcode != CAPI_NOERROR)			continue;		(void) capidrv_addcontr(contr, &profile);	}	return 0;}#ifdef MODULEvoid cleanup_module(void){	capidrv_contr *card, *next;	char rev[10];	char *p;	if ((p = strchr(revision, ':'))) {		strcpy(rev, p + 1);		p = strchr(rev, '$');		*p = 0;	} else {		strcpy(rev, " ??? ");	}	for (card = global.contr_list; card; card = next) {		next = card->next;		capidrv_delcontr(card->contrnr);	}	(void) (*capifuncs->capi_release) (global.appid);	detach_capi_interface(&cuser);	printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);}#endif

⌨️ 快捷键说明

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