i4l.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 575 行 · 第 1/2 页

C
575
字号
		break;	case ISDN_CMD_GETL2:		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2");		break;	case ISDN_CMD_GETL3:		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3");		break;	case ISDN_CMD_GETEAZ:		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ");		break;	case ISDN_CMD_SETSIL:		gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL");		break;	case ISDN_CMD_GETSIL:		gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL");		break;	default:		err("unknown command %d from LL", cntrl->command);		return -EINVAL;	}	return retval;}void gigaset_i4l_cmd(struct cardstate *cs, int cmd){	isdn_ctrl command;	command.driver = cs->myid;	command.command = cmd;	command.arg = 0;	cs->iif.statcallb(&command);}void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd){	isdn_ctrl command;	command.driver = bcs->cs->myid;	command.command = cmd;	command.arg = bcs->channel;	bcs->cs->iif.statcallb(&command);}int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data){	struct bc_state *bcs = at_state->bcs;	unsigned proto;	const char *bc;	size_t length[AT_NUM];	size_t l;	int i;	struct setup_parm *sp = data;	switch (bcs->proto2) {	case ISDN_PROTO_L2_HDLC:		proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */		break;	case ISDN_PROTO_L2_TRANS:		proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */		break;	default:		dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",			__func__, bcs->proto2);		return -EINVAL;	}	switch (sp->si1) {	case 1:		/* audio */		bc = "9090A3";	/* 3.1 kHz audio, A-law */		break;	case 7:		/* data */	default:	/* hope the app knows what it is doing */		bc = "8890";	/* unrestricted digital information */	}	//FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC	length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1;	l = strlen(sp->eazmsn);	length[AT_MSN  ] = l ? 6 + l + 1 + 1 : 0;	length[AT_BC   ] = 5 + strlen(bc) + 1 + 1;	length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */	length[AT_ISO  ] = 6 + 1 + 1 + 1; /* channel: 1 character */	length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */	length[AT_HLC  ] = 0;	for (i = 0; i < AT_NUM; ++i) {		kfree(bcs->commands[i]);		bcs->commands[i] = NULL;		if (length[i] &&		    !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {			dev_err(bcs->cs->dev, "out of memory\n");			return -ENOMEM;		}	}	/* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */	if (sp->phone[0] == '*' && sp->phone[1] == '*') {		/* internal call: translate ** prefix to CTP value */		snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],			 "D%s\r", sp->phone+2);		strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]);	} else {		snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],			 "D%s\r", sp->phone);		strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]);	}	if (bcs->commands[AT_MSN])		snprintf(bcs->commands[AT_MSN], length[AT_MSN],			 "^SMSN=%s\r", sp->eazmsn);	snprintf(bcs->commands[AT_BC   ], length[AT_BC   ],		 "^SBC=%s\r", bc);	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],		 "^SBPR=%u\r", proto);	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],		 "^SISO=%u\r", (unsigned)bcs->channel + 1);	return 0;}int gigaset_isdn_setup_accept(struct at_state_t *at_state){	unsigned proto;	size_t length[AT_NUM];	int i;	struct bc_state *bcs = at_state->bcs;	switch (bcs->proto2) {	case ISDN_PROTO_L2_HDLC:		proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */		break;	case ISDN_PROTO_L2_TRANS:		proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */		break;	default:		dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",			__func__, bcs->proto2);		return -EINVAL;	}	length[AT_DIAL ] = 0;	length[AT_MSN  ] = 0;	length[AT_BC   ] = 0;	length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */	length[AT_ISO  ] = 6 + 1 + 1 + 1; /* channel: 1 character */	length[AT_TYPE ] = 0;	length[AT_HLC  ] = 0;	for (i = 0; i < AT_NUM; ++i) {		kfree(bcs->commands[i]);		bcs->commands[i] = NULL;		if (length[i] &&		    !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {			dev_err(at_state->cs->dev, "out of memory\n");			return -ENOMEM;		}	}	snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],		 "^SBPR=%u\r", proto);	snprintf(bcs->commands[AT_ISO  ], length[AT_ISO  ],		 "^SISO=%u\r", (unsigned) bcs->channel + 1);	return 0;}int gigaset_isdn_icall(struct at_state_t *at_state){	struct cardstate *cs = at_state->cs;	struct bc_state *bcs = at_state->bcs;	isdn_ctrl response;	int retval;	/* fill ICALL structure */	response.parm.setup.si1 = 0;	/* default: unknown */	response.parm.setup.si2 = 0;	response.parm.setup.screen = 0;	//FIXME how to set these?	response.parm.setup.plan = 0;	if (!at_state->str_var[STR_ZBC]) {		/* no BC (internal call): assume speech, A-law */		response.parm.setup.si1 = 1;	} else if (!strcmp(at_state->str_var[STR_ZBC], "8890")) {		/* unrestricted digital information */		response.parm.setup.si1 = 7;	} else if (!strcmp(at_state->str_var[STR_ZBC], "8090A3")) {		/* speech, A-law */		response.parm.setup.si1 = 1;	} else if (!strcmp(at_state->str_var[STR_ZBC], "9090A3")) {		/* 3,1 kHz audio, A-law */		response.parm.setup.si1 = 1;		response.parm.setup.si2 = 2;	} else {		dev_warn(cs->dev, "RING ignored - unsupported BC %s\n",		     at_state->str_var[STR_ZBC]);		return ICALL_IGNORE;	}	if (at_state->str_var[STR_NMBR]) {		strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],			sizeof response.parm.setup.phone - 1);		response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0;	} else		response.parm.setup.phone[0] = 0;	if (at_state->str_var[STR_ZCPN]) {		strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],			sizeof response.parm.setup.eazmsn - 1);		response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0;	} else		response.parm.setup.eazmsn[0] = 0;	if (!bcs) {		dev_notice(cs->dev, "no channel for incoming call\n");		response.command = ISDN_STAT_ICALLW;		response.arg = 0; //FIXME	} else {		gig_dbg(DEBUG_CMD, "Sending ICALL");		response.command = ISDN_STAT_ICALL;		response.arg = bcs->channel; //FIXME	}	response.driver = cs->myid;	retval = cs->iif.statcallb(&response);	gig_dbg(DEBUG_CMD, "Response: %d", retval);	switch (retval) {	case 0:	/* no takers */		return ICALL_IGNORE;	case 1:	/* alerting */		bcs->chstate |= CHS_NOTIFY_LL;		return ICALL_ACCEPT;	case 2:	/* reject */		return ICALL_REJECT;	case 3:	/* incomplete */		dev_warn(cs->dev,		       "LL requested unsupported feature: Incomplete Number\n");		return ICALL_IGNORE;	case 4:	/* proceeding */		/* Gigaset will send ALERTING anyway.		 * There doesn't seem to be a way to avoid this.		 */		return ICALL_ACCEPT;	case 5:	/* deflect */		dev_warn(cs->dev,			 "LL requested unsupported feature: Call Deflection\n");		return ICALL_IGNORE;	default:		dev_err(cs->dev, "LL error %d on ICALL\n", retval);		return ICALL_IGNORE;	}}/* Set Callback function pointer */int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid){	isdn_if *iif = &cs->iif;	gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");	//iif->id[sizeof(iif->id) - 1]=0;	//strncpy(iif->id, isdnid, sizeof(iif->id) - 1);	if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)	    >= sizeof iif->id)		return -ENOMEM; //FIXME EINVAL/...??	iif->owner = THIS_MODULE;	iif->channels = cs->channels;	iif->maxbufsize = MAX_BUF_SIZE;	iif->features = ISDN_FEATURE_L2_TRANS |		ISDN_FEATURE_L2_HDLC |#ifdef GIG_X75		ISDN_FEATURE_L2_X75I |#endif		ISDN_FEATURE_L3_TRANS |		ISDN_FEATURE_P_EURO;	iif->hl_hdrlen = HW_HDR_LEN;		/* Area for storing ack */	iif->command = command_from_LL;	iif->writebuf_skb = writebuf_from_LL;	iif->writecmd = NULL;			/* Don't support isdnctrl */	iif->readstat = NULL;			/* Don't support isdnctrl */	iif->rcvcallb_skb = NULL;		/* Will be set by LL */	iif->statcallb = NULL;			/* Will be set by LL */	if (!register_isdn(iif))		return 0;	cs->myid = iif->channels;		/* Set my device id */	return 1;}

⌨️ 快捷键说明

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