+ * hunt bchannel for incoming setup or retrieve or resume
+ */
+int Pdss1::hunt_bchannel(int channel, int exclusive)
+{
+ struct select_channel *selchannel;
+ struct interface_port *ifport = p_m_mISDNport->ifport;
+ int i;
+
+ chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE);
+ if (exclusive<0)
+ exclusive = 0;
+ if (channel == CHANNEL_NO)
+ add_trace("channel", "request", "no-channel");
+ else
+ add_trace("channel", "request", (channel>0)?"%d%s":"any", channel, exclusive?" (forced)":"");
+ if (channel==CHANNEL_NO && p_type==PORT_TYPE_DSS1_TE_IN) {
+ add_trace("conclusion", NULL, "incoming call-waiting not supported for TE-mode");
+ end_trace();
+ return(-6); // channel unacceptable
+ }
+ if (channel <= 0) /* not given, no channel, whatever.. */
+ channel = CHANNEL_ANY; /* any channel */
+ add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
+ if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
+ add_trace("conclusion", NULL, "all channels are reserved");
+ end_trace();
+ return(-34); // no channel
+ }
+ if (channel == CHANNEL_ANY)
+ goto get_from_list;
+ if (channel > 0) {
+ /* check for given channel in selection list */
+ selchannel = ifport->in_channel;
+ while(selchannel) {
+ if (selchannel->channel == channel || selchannel->channel == CHANNEL_FREE)
+ break;
+ selchannel = selchannel->next;
+ }
+ if (!selchannel)
+ channel = 0;
+
+ /* exclusive channel requests must be in the list */
+ if (exclusive) {
+ /* no exclusive channel */
+ if (!channel) {
+ add_trace("conclusion", NULL, "exclusively requested channel not in list");
+ end_trace();
+ return(-6); // channel unacceptable
+ }
+ /* get index for channel */
+ i = channel-1-(channel>=17);
+ if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16) {
+ add_trace("conclusion", NULL, "exclusively requested channel outside interface range");
+ end_trace();
+ return(-6); // channel unacceptable
+ }
+ /* check if busy */
+ if (p_m_mISDNport->b_port[i] == NULL)
+ goto use_channel;
+ add_trace("conclusion", NULL, "exclusively requested channel is busy");
+ end_trace();
+ return(-6); // channel unacceptable
+ }
+
+ /* requested channels in list will be used */
+ if (channel) {
+ /* get index for channel */
+ i = channel-1-(channel>=17);
+ if (i < 0 || i >= p_m_mISDNport->b_num || channel == 16) {
+ add_trace("info", NULL, "requested channel %d outside interface range", channel);
+ } else /* if inside range (else) check if available */
+ if (p_m_mISDNport->b_port[i] == NULL)
+ goto use_channel;
+ }
+
+ /* if channel is not available or not in list, it must be searched */
+ get_from_list:
+ /* check for first free channel in list */
+ channel = 0;
+ selchannel = ifport->in_channel;
+ while(selchannel) {
+ switch(selchannel->channel) {
+ case CHANNEL_FREE: /* free channel */
+ add_trace("hunting", "channel", "free");
+ if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num)
+ break; /* all channel in use or reserverd */
+ /* find channel */
+ i = 0;
+ while(i < p_m_mISDNport->b_num) {
+ if (p_m_mISDNport->b_port[i] == NULL) {
+ channel = i+1+(i>=15);
+ break;
+ }
+ i++;
+ }
+ break;
+
+ default:
+ add_trace("hunting", "channel", "%d", selchannel->channel);
+ if (selchannel->channel<1 || selchannel->channel==16)
+ break; /* invalid channels */
+ i = selchannel->channel-1-(selchannel->channel>=17);
+ if (i >= p_m_mISDNport->b_num)
+ break; /* channel not in port */
+ if (p_m_mISDNport->b_port[i] == NULL) {
+ channel = selchannel->channel;
+ break;
+ }
+ break;
+ }
+ if (channel)
+ break; /* found channel */
+ selchannel = selchannel->next;
+ }
+ if (!channel) {
+ add_trace("conclusion", NULL, "no channel available");
+ end_trace();
+ return(-6); // channel unacceptable
+ }
+ }
+use_channel:
+ add_trace("conclusion", NULL, "channel available");
+ add_trace("connect", "channel", "%d", channel);
+ end_trace();
+ return(channel);
+}
+
+/*