示例#1
0
static void start_channel(struct pri *pri, pri_event *e)
{
	int channo = e->ring.channel;
	int		flag = 1;
	pri_event_ring	*ring = &e->ring;

	if(channo == -1) {
		channo = e->ring.channel = get_free_channel(MAX_CHAN);

		if(channo == DCHANNEL_TIMESLOT)
			channo = e->ring.channel = get_free_channel(MAX_CHAN);
		  
		
		fprintf(stdout, "Any channel selected: %d\n", channo);

		if(!channo) {
		  pri_release(pri, ring->call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
		  fprintf(stdout, "Abort call due to no avl B channels\n");
		  return;
		}

		flag = 0;
	}
	/* Make sure it's a valid number */
	if ((channo >= MAX_CHAN) || (channo < 0)) { 
		fprintf(stderr, "--!! Channel %d is out of range\n", channo);
		return;
	}

	/* Make sure nothing is there */
	if (chans[channo].pid) {
		fprintf(stderr, "--!! Channel %d still has a call on it, ending it...\n", channo);
		hangup_channel(channo);
		/* Wait for it to die */
		while(chans[channo].pid)
			usleep(100);
	}

	/* Record call number */
	chans[channo].call = e->ring.call;

	/* Answer the line */
	if(flag) {
		pri_answer(pri, chans[channo].call, channo, 1);
	} else {
		pri_need_more_info(pri, chans[channo].call, channo, 1);
	}

	/* Launch a process to handle it */
	launch_channel(channo);

}
void
call_arrival_event(Simulation_Run_Ptr simulation_run, void * ptr)
{
  Call_Ptr new_call;
  Channel_Ptr free_channel;
  Simulation_Run_Data_Ptr sim_data;
  double now;

  now = simulation_run_get_time(simulation_run);

  sim_data = simulation_run_data(simulation_run);
  sim_data->call_arrival_count++;

  if((free_channel = get_free_channel(simulation_run)) != NULL) {

    /* Start the call. */
    new_call = (Call_Ptr) xmalloc(sizeof(Call));
    new_call->arrive_time = now;
    new_call->call_duration = get_call_duration();

    server_put(free_channel, (void*) new_call);
    new_call->channel = free_channel;

    schedule_end_call_on_channel_event(simulation_run,
				       now + new_call->call_duration,
				       (void *) free_channel);
  } else {
    /* The call was blocked. */
    sim_data->blocked_call_count++;
  }

  /* Schedule the next call arrival. */
  schedule_call_arrival_event(simulation_run,
	      now + exponential_generator((double) 1/Call_ARRIVALRATE));
}
示例#3
0
static int
route_call(layer4_t *l4)
{
	layer4_t	*newl4;

	fprintf(stderr, "%s: msn ", __FUNCTION__);
	display_NR_IE(l4->msn);
	fprintf(stderr, "%s:  nr ", __FUNCTION__);
	display_NR_IE(l4->nr);
	if (l4->usednr->typ == NR_TYPE_INTERN) {
		newl4 = get_free_channel(&kern_if, -1, NULL);
		if (!newl4) {
			l4->cause_loc = CAUSE_LOC_PNET_LOCUSER;
			l4->cause_val = CAUSE_USER_BUSY;
			l4->progress = PROGRESS_TONE;
			if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST,
				l4->channel, 0, NULL, 0);
			return(0);
		}
		l4->sdata = newl4;
		l4->rdata = newl4;
		newl4->sdata = l4;
		newl4->rdata = l4;
		l4->sbuf = &newl4->rbuf;
		newl4->sbuf = &l4->rbuf;
		newl4->msn[0] = l4->usednr->len +1;
		newl4->msn[1] = 0x81;
		memcpy(&newl4->msn[2], l4->usednr->nr, l4->usednr->len);
		if (l4->msn[0])
			memcpy(newl4->nr, l4->msn, l4->msn[0] + 1);
		newl4->l1_prot = ISDN_PID_L1_B_64TRANS;
		if_link(newl4->nst, man_down, MAN_SETUP | REQUEST,
			newl4->channel, 0, NULL, 0);
	} else if (l4->usednr->typ == NR_TYPE_AUDIO) {
		l4->sdata = NULL;
		l4->rdata = NULL;
		strcpy(l4->display,"connect to AUDIO");
		do_connect(l4);
		l4->display[0] = 0;
		deactivate_bchannel(l4);
		setup_bchannel_rawdev(l4);
		activate_bchannel(l4);
	} else if (l4->usednr->typ == NR_TYPE_VOIP) {
		l4->sdata = NULL;
		l4->rdata = NULL;
		sprintf(l4->display,"calling %s", l4->usednr->name);
		do_alert(l4);
		sprintf(l4->display,"connect to %s", l4->usednr->name);
		do_connect(l4);
		l4->display[0] = 0;
		deactivate_bchannel(l4);
		setup_bchannel_rawdev(l4);
		activate_bchannel(l4);
	}
	return(0);
}
示例#4
0
文件: ev-layer.c 项目: 020gzh/linux
static void do_action(int action, struct cardstate *cs,
		      struct bc_state *bcs,
		      struct at_state_t **p_at_state, char **pp_command,
		      int *p_genresp, int *p_resp_code,
		      struct event_t *ev)
{
	struct at_state_t *at_state = *p_at_state;
	struct bc_state *bcs2;
	unsigned long flags;

	int channel;

	unsigned char *s, *e;
	int i;
	unsigned long val;

	switch (action) {
	case ACT_NOTHING:
		break;
	case ACT_TIMEOUT:
		at_state->waiting = 1;
		break;
	case ACT_INIT:
		cs->at_state.pending_commands &= ~PC_INIT;
		cs->cur_at_seq = SEQ_NONE;
		cs->mode = M_UNIMODEM;
		spin_lock_irqsave(&cs->lock, flags);
		if (!cs->cidmode) {
			spin_unlock_irqrestore(&cs->lock, flags);
			gigaset_free_channels(cs);
			cs->mstate = MS_READY;
			break;
		}
		spin_unlock_irqrestore(&cs->lock, flags);
		cs->at_state.pending_commands |= PC_CIDMODE;
		gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE");
		cs->commands_pending = 1;
		break;
	case ACT_FAILINIT:
		dev_warn(cs->dev, "Could not initialize the device.\n");
		cs->dle = 0;
		init_failed(cs, M_UNKNOWN);
		cs->cur_at_seq = SEQ_NONE;
		break;
	case ACT_CONFIGMODE:
		init_failed(cs, M_CONFIG);
		cs->cur_at_seq = SEQ_NONE;
		break;
	case ACT_SETDLE1:
		cs->dle = 1;
		/* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */
		cs->inbuf[0].inputstate &=
			~(INS_command | INS_DLE_command);
		break;
	case ACT_SETDLE0:
		cs->dle = 0;
		cs->inbuf[0].inputstate =
			(cs->inbuf[0].inputstate & ~INS_DLE_command)
			| INS_command;
		break;
	case ACT_CMODESET:
		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
			gigaset_free_channels(cs);
			cs->mstate = MS_READY;
		}
		cs->mode = M_CID;
		cs->cur_at_seq = SEQ_NONE;
		break;
	case ACT_UMODESET:
		cs->mode = M_UNIMODEM;
		cs->cur_at_seq = SEQ_NONE;
		break;
	case ACT_FAILCMODE:
		cs->cur_at_seq = SEQ_NONE;
		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
			init_failed(cs, M_UNKNOWN);
			break;
		}
		if (reinit_and_retry(cs, -1) < 0)
			schedule_init(cs, MS_RECOVER);
		break;
	case ACT_FAILUMODE:
		cs->cur_at_seq = SEQ_NONE;
		schedule_init(cs, MS_RECOVER);
		break;
	case ACT_HUPMODEM:
		/* send "+++" (hangup in unimodem mode) */
		if (cs->connected) {
			struct cmdbuf_t *cb;

			cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC);
			if (!cb) {
				dev_err(cs->dev, "%s: out of memory\n",
					__func__);
				return;
			}
			memcpy(cb->buf, "+++", 3);
			cb->len = 3;
			cb->offset = 0;
			cb->next = NULL;
			cb->wake_tasklet = NULL;
			cs->ops->write_cmd(cs, cb);
		}
		break;
	case ACT_RING:
		/* get fresh AT state structure for new CID */
		at_state = get_free_channel(cs, ev->parameter);
		if (!at_state) {
			dev_warn(cs->dev,
				 "RING ignored: could not allocate channel structure\n");
			break;
		}

		/* initialize AT state structure
		 * note that bcs may be NULL if no B channel is free
		 */
		at_state->ConState = 700;
		for (i = 0; i < STR_NUM; ++i) {
			kfree(at_state->str_var[i]);
			at_state->str_var[i] = NULL;
		}
		at_state->int_var[VAR_ZCTP] = -1;

		spin_lock_irqsave(&cs->lock, flags);
		at_state->timer_expires = RING_TIMEOUT;
		at_state->timer_active = 1;
		spin_unlock_irqrestore(&cs->lock, flags);
		break;
	case ACT_ICALL:
		handle_icall(cs, bcs, at_state);
		break;
	case ACT_FAILSDOWN:
		dev_warn(cs->dev, "Could not shut down the device.\n");
		/* fall through */
	case ACT_FAKESDOWN:
	case ACT_SDOWN:
		cs->cur_at_seq = SEQ_NONE;
		finish_shutdown(cs);
		break;
	case ACT_CONNECT:
		if (cs->onechannel) {
			at_state->pending_commands |= PC_DLE1;
			cs->commands_pending = 1;
			break;
		}
		bcs->chstate |= CHS_D_UP;
		gigaset_isdn_connD(bcs);
		cs->ops->init_bchannel(bcs);
		break;
	case ACT_DLE1:
		cs->cur_at_seq = SEQ_NONE;
		bcs = cs->bcs + cs->curchannel;

		bcs->chstate |= CHS_D_UP;
		gigaset_isdn_connD(bcs);
		cs->ops->init_bchannel(bcs);
		break;
	case ACT_FAKEHUP:
		at_state->int_var[VAR_ZSAU] = ZSAU_NULL;
		/* fall through */
	case ACT_DISCONNECT:
		cs->cur_at_seq = SEQ_NONE;
		at_state->cid = -1;
		if (!bcs) {
			disconnect_nobc(p_at_state, cs);
		} else if (cs->onechannel && cs->dle) {
			/* Check for other open channels not needed:
			 * DLE only used for M10x with one B channel.
			 */
			at_state->pending_commands |= PC_DLE0;
			cs->commands_pending = 1;
		} else {
			disconnect_bc(at_state, cs, bcs);
		}
		break;
	case ACT_FAKEDLE0:
		at_state->int_var[VAR_ZDLE] = 0;
		cs->dle = 0;
		/* fall through */
	case ACT_DLE0:
		cs->cur_at_seq = SEQ_NONE;
		bcs2 = cs->bcs + cs->curchannel;
		disconnect_bc(&bcs2->at_state, cs, bcs2);
		break;
	case ACT_ABORTHUP:
		cs->cur_at_seq = SEQ_NONE;
		dev_warn(cs->dev, "Could not hang up.\n");
		at_state->cid = -1;
		if (!bcs)
			disconnect_nobc(p_at_state, cs);
		else if (cs->onechannel)
			at_state->pending_commands |= PC_DLE0;
		else
			disconnect_bc(at_state, cs, bcs);
		schedule_init(cs, MS_RECOVER);
		break;
	case ACT_FAILDLE0:
		cs->cur_at_seq = SEQ_NONE;
		dev_warn(cs->dev, "Error leaving DLE mode.\n");
		cs->dle = 0;
		bcs2 = cs->bcs + cs->curchannel;
		disconnect_bc(&bcs2->at_state, cs, bcs2);
		schedule_init(cs, MS_RECOVER);
		break;
	case ACT_FAILDLE1:
		cs->cur_at_seq = SEQ_NONE;
		dev_warn(cs->dev,
			 "Could not enter DLE mode. Trying to hang up.\n");
		channel = cs->curchannel;
		cs->bcs[channel].at_state.pending_commands |= PC_HUP;
		cs->commands_pending = 1;
		break;

	case ACT_CID: /* got cid; start dialing */
		cs->cur_at_seq = SEQ_NONE;
		channel = cs->curchannel;
		if (ev->parameter > 0 && ev->parameter <= 65535) {
			cs->bcs[channel].at_state.cid = ev->parameter;
			cs->bcs[channel].at_state.pending_commands |=
				PC_DIAL;
			cs->commands_pending = 1;
			break;
		}
		/* bad cid: fall through */
	case ACT_FAILCID:
		cs->cur_at_seq = SEQ_NONE;
		channel = cs->curchannel;
		if (reinit_and_retry(cs, channel) < 0) {
			dev_warn(cs->dev,
				 "Could not get a call ID. Cannot dial.\n");
			bcs2 = cs->bcs + channel;
			disconnect_bc(&bcs2->at_state, cs, bcs2);
		}
		break;
	case ACT_ABORTCID:
		cs->cur_at_seq = SEQ_NONE;
		bcs2 = cs->bcs + cs->curchannel;
		disconnect_bc(&bcs2->at_state, cs, bcs2);
		break;

	case ACT_DIALING:
	case ACT_ACCEPTED:
		cs->cur_at_seq = SEQ_NONE;
		break;

	case ACT_ABORTACCEPT:	/* hangup/error/timeout during ICALL procssng */
		if (bcs)
			disconnect_bc(at_state, cs, bcs);
		else
			disconnect_nobc(p_at_state, cs);
		break;

	case ACT_ABORTDIAL:	/* error/timeout during dial preparation */
		cs->cur_at_seq = SEQ_NONE;
		at_state->pending_commands |= PC_HUP;
		cs->commands_pending = 1;
		break;

	case ACT_REMOTEREJECT:	/* DISCONNECT_IND after dialling */
	case ACT_CONNTIMEOUT:	/* timeout waiting for ZSAU=ACTIVE */
	case ACT_REMOTEHUP:	/* DISCONNECT_IND with established connection */
		at_state->pending_commands |= PC_HUP;
		cs->commands_pending = 1;
		break;
	case ACT_GETSTRING: /* warning: RING, ZDLE, ...
			       are not handled properly anymore */
		at_state->getstring = 1;
		break;
	case ACT_SETVER:
		if (!ev->ptr) {
			*p_genresp = 1;
			*p_resp_code = RSP_ERROR;
			break;
		}
		s = ev->ptr;

		if (!strcmp(s, "OK")) {
			/* OK without version string: assume old response */
			*p_genresp = 1;
			*p_resp_code = RSP_NONE;
			break;
		}

		for (i = 0; i < 4; ++i) {
			val = simple_strtoul(s, (char **) &e, 10);
			if (val > INT_MAX || e == s)
				break;
			if (i == 3) {
				if (*e)
					break;
			} else if (*e != '.')
				break;
			else
				s = e + 1;
			cs->fwver[i] = val;
		}
		if (i != 4) {
			*p_genresp = 1;
			*p_resp_code = RSP_ERROR;
			break;
		}
		cs->gotfwver = 0;
		break;
	case ACT_GOTVER:
		if (cs->gotfwver == 0) {
			cs->gotfwver = 1;
			gig_dbg(DEBUG_EVENT,
				"firmware version %02d.%03d.%02d.%02d",
				cs->fwver[0], cs->fwver[1],
				cs->fwver[2], cs->fwver[3]);
			break;
		}
		/* fall through */
	case ACT_FAILVER:
		cs->gotfwver = -1;
		dev_err(cs->dev, "could not read firmware version.\n");
		break;
	case ACT_ERROR:
		gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d",
			__func__, at_state->ConState);
		cs->cur_at_seq = SEQ_NONE;
		break;
	case ACT_DEBUG:
		gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
			__func__, ev->type, at_state->ConState);
		break;
	case ACT_WARN:
		dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n",
			 __func__, ev->type, at_state->ConState);
		break;
	case ACT_ZCAU:
		dev_warn(cs->dev, "cause code %04x in connection state %d.\n",
			 ev->parameter, at_state->ConState);
		break;

	/* events from the LL */

	case ACT_DIAL:
		if (!ev->ptr) {
			*p_genresp = 1;
			*p_resp_code = RSP_ERROR;
			break;
		}
		start_dial(at_state, ev->ptr, ev->parameter);
		break;
	case ACT_ACCEPT:
		start_accept(at_state);
		break;
	case ACT_HUP:
		at_state->pending_commands |= PC_HUP;
		gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP");
		cs->commands_pending = 1;
		break;

	/* hotplug events */

	case ACT_STOP:
		do_stop(cs);
		break;
	case ACT_START:
		do_start(cs);
		break;

	/* events from the interface */

	case ACT_IF_LOCK:
		cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
		cs->waiting = 0;
		wake_up(&cs->waitqueue);
		break;
	case ACT_IF_VER:
		if (ev->parameter != 0)
			cs->cmd_result = -EINVAL;
		else if (cs->gotfwver != 1) {
			cs->cmd_result = -ENOENT;
		} else {
			memcpy(ev->arg, cs->fwver, sizeof cs->fwver);
			cs->cmd_result = 0;
		}
		cs->waiting = 0;
		wake_up(&cs->waitqueue);
		break;

	/* events from the proc file system */

	case ACT_PROC_CIDMODE:
		spin_lock_irqsave(&cs->lock, flags);
		if (ev->parameter != cs->cidmode) {
			cs->cidmode = ev->parameter;
			if (ev->parameter) {
				cs->at_state.pending_commands |= PC_CIDMODE;
				gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE");
			} else {
				cs->at_state.pending_commands |= PC_UMMODE;
				gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE");
			}
			cs->commands_pending = 1;
		}
		spin_unlock_irqrestore(&cs->lock, flags);
		cs->waiting = 0;
		wake_up(&cs->waitqueue);
		break;

	/* events from the hardware drivers */

	case ACT_NOTIFY_BC_DOWN:
		bchannel_down(bcs);
		break;
	case ACT_NOTIFY_BC_UP:
		bchannel_up(bcs);
		break;
	case ACT_SHUTDOWN:
		do_shutdown(cs);
		break;


	default:
		if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) {
			*pp_command = at_state->bcs->commands[action - ACT_CMD];
			if (!*pp_command) {
				*p_genresp = 1;
				*p_resp_code = RSP_NULL;
			}
		} else
			dev_err(cs->dev, "%s: action==%d!\n", __func__, action);
	}
}