1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
15 *****TBD: THIS TEXT IS OLD ******
19 Create port/endpoint instance and send SETUP message to endpoint.
21 Send CONNECT message to endpoint.
22 port instance inactive:
23 Put inactive port instance active. Send RETRIEVE message to endpoint.
25 Release active port instance. Send RELEASE message to endpoint if exists.
26 inactive port instance:
27 Send ring request. Use caller ID on incomming call or connected ID on outgoing call.
29 active port instance not connected:
30 Release active port instance. Send RELEASE message to endpoint if exists.
31 active port instance connected:
32 Put active port instance inactive. Send HOLD MESSAGE to endpoint.
33 inactive port instance:
34 Put inactive port instance active. Send RETRIEVE message to endpoint.
35 no inactive port instance:
36 Create port/endpoint instance and send SETUP message to endpoint.
38 active port instance in incomming overlap state:
39 Send INFORMATION message to endpoint.
40 active port instance in other state:
41 Send KEYPAD message to endpoint, if exists.
44 Create port instance and send ALERTING message to endpoint.
45 Send ring request. Use caller ID.
46 only one instance active:
47 Create port instance and send ALERTING message to endpoint.
48 Send knock sound. Send ALERTING message to endpoint.
50 Send RELEASE message (cause = BUSY) to endpoint.
51 PROCEEDING / ALERTING / CONNECT message:
54 is inactive port instance:
55 Release port instance. Send RELEASE message to endpoint.
57 is active port instance:
58 Create hangup tone (release tone)
59 is inactive port instance:
60 Release port instance.
66 //#include <sys/socket.h>
70 #ifdef ISDN_P_FXS_POTS
72 static int fxs_age = 0;
74 static int delete_event(struct lcr_work *work, void *instance, int index);
76 static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index)
78 class Pfxs *pfxs = (class Pfxs *)instance;
80 /* allow DTMF dialing now */
81 PDEBUG(DEBUG_ISDN, "%s: allow DTMF now\n", pfxs->p_name);
82 pfxs->p_m_fxs_allow_dtmf = 1;
90 Pfxs::Pfxs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, struct interface *interface, int mode) : PmISDN(type, mISDNport, portname, settings, interface, 0, 0, mode)
92 p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
94 memset(&p_m_fxs_delete, 0, sizeof(p_m_fxs_delete));
95 add_work(&p_m_fxs_delete, delete_event, this, 0);
96 p_m_fxs_allow_dtmf = 0;
97 memset(&p_m_fxs_dtmf_timer, 0, sizeof(p_m_fxs_dtmf_timer));
98 add_timer(&p_m_fxs_dtmf_timer, dtmf_timeout, this, 0);
99 p_m_fxs_age = fxs_age++;
100 p_m_fxs_knocking = 0;
102 PDEBUG(DEBUG_ISDN, "Created new FXSPort(%s). Currently %d objects use, FXS port #%d\n", portname, mISDNport->use, p_m_portnum);
111 del_timer(&p_m_fxs_dtmf_timer);
112 del_work(&p_m_fxs_delete);
115 /* deletes only if l3id is release, otherwhise it will be triggered then */
116 static int delete_event(struct lcr_work *work, void *instance, int index)
118 class Pfxs *pots = (class Pfxs *)instance;
126 int Pfxs::hunt_bchannel(void)
128 if (p_m_mISDNport->b_num < 1)
130 if (p_m_mISDNport->b_port[0])
135 int Pfxs::ph_control_pots(unsigned int cont, unsigned char *data, int len)
137 unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+len];
138 struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
139 unsigned int *d = (unsigned int *)(buffer+MISDN_HEADER_LEN);
142 ctrl->prim = PH_CONTROL_REQ;
146 memcpy(d, data, len);
147 ret = sendto(p_m_mISDNport->pots_sock.fd, buffer, MISDN_HEADER_LEN+sizeof(int)+len, 0, NULL, 0);
149 PERROR("Failed to send to socket %d\n", p_m_mISDNport->pots_sock.fd);
154 void Pfxs::pickup_ind(unsigned int cont)
156 struct interface *interface = p_m_mISDNport->ifport->interface;
157 class Endpoint *epoint;
158 struct lcr_msg *message;
161 p_m_fxs_age = fxs_age++;
163 if (p_m_fxs_knocking) {
164 ph_control_pots(POTS_CW_OFF, NULL, 0);
165 p_m_fxs_knocking = 0;
168 chan_trace_header(p_m_mISDNport, this, "PICKUP", DIRECTION_NONE);
170 if (interface->ifmsn && interface->ifmsn->msn[0]) {
171 SCPY(p_callerinfo.id, interface->ifmsn->msn);
172 add_trace("caller", "ID", "%s", p_callerinfo.id);
174 p_callerinfo.present = INFO_PRESENT_ALLOWED;
175 p_callerinfo.isdn_port = p_m_portnum;
176 SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
177 p_capainfo.source_mode = B_MODE_TRANSPARENT;
178 p_capainfo.bearer_capa = INFO_BC_AUDIO;
179 p_capainfo.bearer_info1 = 0x80 + ((options.law=='a')?3:2);
180 p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
182 if ((cont & (~POTS_KP_MASK)) == POTS_KP_VAL) {
183 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
184 p_dialinginfo.id[0] = cont & POTS_KP_MASK;
187 if (!p_m_b_channel) {
188 PDEBUG(DEBUG_ISDN, "Pfxs(%s) alloc bchannel\n", p_name);
190 ret = channel = hunt_bchannel();
195 ret = seize_bchannel(channel, 1);
199 * NOTE: we send MT_RELEASE_COMPLETE to "REJECT" the channel
200 * in response to the setup
202 add_trace("error", NULL, "no b-channel");
204 new_state(PORT_STATE_RELEASE);
205 trigger_work(&p_m_fxs_delete);
209 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
211 PDEBUG(DEBUG_ISDN, "Pfxs(%s) bchannel is already active\n", p_name);
214 /* create endpoint */
216 FATAL("Incoming call but already got an endpoint.\n");
217 if (!(epoint = new Endpoint(p_serial, 0)))
218 FATAL("No memory for Endpoint instance\n");
219 epoint->ep_app = new_endpointapp(epoint, 0, p_m_mISDNport->ifport->interface->app); //incoming
220 epointlist_new(epoint->ep_serial);
222 /* indicate flash control */
223 if (cont == POTS_HOOK_FLASH || cont == POTS_EARTH_KEY)
224 p_dialinginfo.flash = 1;
226 /* send setup message to endpoit */
227 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
228 message->param.setup.isdn_port = p_m_portnum;
229 message->param.setup.port_type = p_type;
230 // message->param.setup.dtmf = !p_m_mISDNport->ifport->nodtmf;
231 memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
232 memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
233 memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
234 message_put(message);
236 new_state(PORT_STATE_IN_OVERLAP);
238 schedule_timer(&p_m_fxs_dtmf_timer, 0, 500000);
241 void Pfxs::hangup_ind(unsigned int cont)
243 struct lcr_msg *message;
245 /* deactivate bchannel */
246 chan_trace_header(p_m_mISDNport, this, "HANGUP", DIRECTION_NONE);
249 PDEBUG(DEBUG_ISDN, "Pfxs(%s) drop bchannel\n", p_name);
251 /* send release message, if not already */
253 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
254 message->param.disconnectinfo.cause = 16;
255 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
256 message_put(message);
258 new_state(PORT_STATE_RELEASE);
259 trigger_work(&p_m_fxs_delete);
262 void Pfxs::answer_ind(unsigned int cont)
264 struct lcr_msg *message;
267 if (p_m_fxs_knocking) {
268 ph_control_pots(POTS_CW_OFF, NULL, 0);
269 p_m_fxs_knocking = 0;
272 chan_trace_header(p_m_mISDNport, this, "ANSWER", DIRECTION_NONE);
273 if (!p_m_b_channel) {
274 PDEBUG(DEBUG_ISDN, "Pfxs(%s) alloc bchannel\n", p_name);
276 ret = channel = hunt_bchannel();
281 ret = seize_bchannel(channel, 1);
285 * NOTE: we send MT_RELEASE_COMPLETE to "REJECT" the channel
286 * in response to the setup
288 add_trace("error", NULL, "no b-channel");
290 new_state(PORT_STATE_RELEASE);
291 trigger_work(&p_m_fxs_delete);
295 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
297 PDEBUG(DEBUG_ISDN, "Pfxs(%s) bchannel is already active\n", p_name);
302 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
303 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
304 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
305 message_put(message);
307 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
308 message_put(message);
311 new_state(PORT_STATE_CONNECT);
314 void Pfxs::hold_ind(unsigned int cont)
316 struct lcr_msg *message;
318 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
319 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
320 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
321 message_put(message);
323 /* deactivate bchannel */
324 chan_trace_header(p_m_mISDNport, this, "HOLD", DIRECTION_NONE);
327 PDEBUG(DEBUG_ISDN, "Pfxs(%s) drop bchannel\n", p_name);
332 void Pfxs::retrieve_ind(unsigned int cont)
334 struct lcr_msg *message;
337 p_m_fxs_age = fxs_age++;
339 if (p_m_fxs_knocking) {
340 ph_control_pots(POTS_CW_OFF, NULL, 0);
341 p_m_fxs_knocking = 0;
344 if (cont == POTS_ON_HOOK) {
345 const char *callerid;
347 if (p_state == PORT_STATE_CONNECT) {
348 new_state(PORT_STATE_OUT_ALERTING);
350 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
351 message_put(message);
353 chan_trace_header(p_m_mISDNport, this, "RING (retrieve)", DIRECTION_NONE);
355 chan_trace_header(p_m_mISDNport, this, "RING (after knocking)", DIRECTION_NONE);
356 if (p_type == PORT_TYPE_POTS_FXS_IN) {
357 if (p_connectinfo.id[0]) {
358 callerid = numberrize_callerinfo(p_connectinfo.id, p_connectinfo.ntype, options.national, options.international);
359 add_trace("connect", "number", callerid);
361 callerid = p_dialinginfo.id;
362 add_trace("dialing", "number", callerid);
365 callerid = numberrize_callerinfo(p_callerinfo.id, p_callerinfo.ntype, options.national, options.international);
366 add_trace("caller", "id", callerid);
368 ph_control_pots(POTS_RING_ON, (unsigned char *)callerid, strlen(callerid));
373 chan_trace_header(p_m_mISDNport, this, "RETRIEVE", DIRECTION_NONE);
374 if (!p_m_b_channel) {
375 PDEBUG(DEBUG_ISDN, "Pfxs(%s) alloc bchannel\n", p_name);
377 ret = channel = hunt_bchannel();
382 ret = seize_bchannel(channel, 1);
386 * NOTE: we send MT_RELEASE_COMPLETE to "REJECT" the channel
387 * in response to the setup
389 add_trace("error", NULL, "no b-channel");
391 new_state(PORT_STATE_RELEASE);
392 trigger_work(&p_m_fxs_delete);
396 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
398 PDEBUG(DEBUG_ISDN, "Pfxs(%s) bchannel is already active\n", p_name);
402 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
403 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
404 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
405 message_put(message);
408 void Pfxs::keypulse_ind(unsigned int cont)
410 struct lcr_msg *message;
412 p_m_fxs_allow_dtmf = 0; /* disable DTMF from now on */
413 chan_trace_header(p_m_mISDNport, this, "PULSE", DIRECTION_NONE);
414 add_trace("KP", NULL, "%c", cont & DTMF_TONE_MASK);
416 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
417 message->param.information.id[0] = cont & POTS_KP_MASK;
418 PDEBUG(DEBUG_ISDN, "Pfxs(%s) PH_CONTROL INDICATION KP digit '%c'\n", p_name, message->param.information.id[0]);
419 message_put(message);
422 void Pfxs::reject_ind(unsigned int cont)
424 struct lcr_msg *message;
426 if (p_m_fxs_knocking) {
427 ph_control_pots(POTS_CW_OFF, NULL, 0);
428 p_m_fxs_knocking = 0;
431 /* deactivate bchannel */
432 chan_trace_header(p_m_mISDNport, this, "REJECT", DIRECTION_NONE);
435 PDEBUG(DEBUG_ISDN, "Pfxs(%s) drop bchannel\n", p_name);
437 /* send release message, if not already */
439 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
440 message->param.disconnectinfo.cause = 16;
441 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
442 message_put(message);
444 new_state(PORT_STATE_RELEASE);
445 trigger_work(&p_m_fxs_delete);
449 void Pfxs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
451 struct lcr_msg *message;
454 struct epoint_list *epointlist;
455 const char *callerid;
458 memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
459 memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
461 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_ALERTING);
462 message_put(message);
464 new_state(PORT_STATE_OUT_ALERTING);
466 /* attach only if not already */
467 epointlist = p_epointlist;
469 if (epointlist->epoint_id == epoint_id)
471 epointlist = epointlist->next;
474 epointlist_new(epoint_id);
476 /* find port in connected active state */
479 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
480 pots = (class Pfxs *)port;
481 if (pots->p_m_mISDNport == p_m_mISDNport) {
484 if (pots->p_state == PORT_STATE_CONNECT && !pots->p_m_hold)
492 PDEBUG(DEBUG_ISDN, "Pfxs(%s) knock because there is an ongoing active call\n", p_name);
493 chan_trace_header(p_m_mISDNport, this, "KNOCK", DIRECTION_NONE);
494 callerid = numberrize_callerinfo(p_callerinfo.id, p_callerinfo.ntype, options.national, options.international);
495 add_trace("caller", "id", callerid);
497 ph_control_pots(POTS_CW_ON, (unsigned char *)callerid, strlen(callerid));
498 p_m_fxs_knocking = 1;
502 /* reject call, because we have a call, but we are not connected */
503 PDEBUG(DEBUG_ISDN, "Pfxs(%s) reject because there is an ongoing and incomplete call\n", p_name);
504 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
505 message->param.disconnectinfo.cause = 17; // busy
506 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
507 message_put(message);
508 new_state(PORT_STATE_RELEASE);
509 trigger_work(&p_m_fxs_delete);
512 PDEBUG(DEBUG_ISDN, "Pfxs(%s) ring because there is not calll\n", p_name);
513 chan_trace_header(p_m_mISDNport, this, "RING", DIRECTION_NONE);
514 callerid = numberrize_callerinfo(p_callerinfo.id, p_callerinfo.ntype, options.national, options.international);
515 add_trace("caller", "id", callerid);
517 ph_control_pots(POTS_RING_ON, (unsigned char *)callerid, strlen(callerid));
520 void Pfxs::message_proceeding(unsigned int epoint_id, int message_id, union parameter *param)
522 new_state(PORT_STATE_IN_PROCEEDING);
525 void Pfxs::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
527 new_state(PORT_STATE_IN_ALERTING);
530 void Pfxs::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
532 new_state(PORT_STATE_CONNECT);
534 memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(struct connect_info));
537 void Pfxs::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
539 if (p_state == PORT_STATE_OUT_ALERTING) {
540 if (p_m_fxs_knocking) {
541 ph_control_pots(POTS_CW_OFF, NULL, 0);
542 p_m_fxs_knocking = 0;
544 ph_control_pots(POTS_RING_OFF, NULL, 0);
547 struct lcr_msg *message;
548 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
549 message->param.disconnectinfo.cause = 16;
550 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
551 message_put(message);
553 free_epointid(epoint_id);
554 new_state(PORT_STATE_RELEASE);
555 trigger_work(&p_m_fxs_delete);
559 new_state(PORT_STATE_OUT_DISCONNECT);
562 void Pfxs::message_release(unsigned int epoint_id, int message_id, union parameter *param)
564 chan_trace_header(p_m_mISDNport, this, "CLEAR", DIRECTION_NONE);
567 if (p_state == PORT_STATE_OUT_ALERTING) {
568 if (p_m_fxs_knocking) {
569 ph_control_pots(POTS_CW_OFF, NULL, 0);
570 p_m_fxs_knocking = 0;
572 ph_control_pots(POTS_RING_OFF, NULL, 0);
574 trigger_work(&p_m_fxs_delete);
576 if (p_state == PORT_STATE_CONNECT) {
578 set_tone("", "release");
580 trigger_work(&p_m_fxs_delete);
583 new_state(PORT_STATE_RELEASE);
585 free_epointid(epoint_id);
589 * endpoint sends messages to the port
591 int Pfxs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
593 if (PmISDN::message_epoint(epoint_id, message_id, param))
597 case MESSAGE_SETUP: /* dial-out command received from epoint */
598 message_setup(epoint_id, message_id, param);
601 case MESSAGE_PROCEEDING: /* call of endpoint is proceeding */
602 message_proceeding(epoint_id, message_id, param);
605 case MESSAGE_ALERTING: /* call of endpoint is ringing */
606 message_alerting(epoint_id, message_id, param);
609 case MESSAGE_CONNECT: /* call of endpoint is connected */
610 message_connect(epoint_id, message_id, param);
613 case MESSAGE_DISCONNECT: /* call has been disconnected */
614 message_disconnect(epoint_id, message_id, param);
617 case MESSAGE_RELEASE: /* release isdn port */
618 if (p_state==PORT_STATE_RELEASE) {
621 message_release(epoint_id, message_id, param);
629 * data from isdn-stack (layer-1) to pbx (port class)
631 int stack2manager_fxs(struct mISDNport *mISDNport, unsigned int cont)
634 class Pfxs *pots, *latest_pots = NULL, *alerting_pots = NULL;
638 PDEBUG(DEBUG_ISDN, "cont(0x%x)\n", cont);
640 if ((cont & (~POTS_KP_MASK)) == POTS_KP_VAL) {
641 /* find port in dialing state */
644 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
645 pots = (class Pfxs *)port;
646 if (pots->p_m_mISDNport == mISDNport
647 && pots->p_state == PORT_STATE_IN_OVERLAP)
653 pots->keypulse_ind(cont);
664 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
665 pots = (class Pfxs *)port;
666 if (pots->p_m_mISDNport == mISDNport
667 && pots->p_state == PORT_STATE_OUT_ALERTING)
673 pots->answer_ind(cont);
678 /* creating port object */
679 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
680 pots = new Pfxs(PORT_TYPE_POTS_FXS_IN, mISDNport, name, NULL, mISDNport->ifport->interface, B_MODE_TRANSPARENT);
682 FATAL("Failed to create Port instance\n");
683 pots->pickup_ind(cont);
687 if (mISDNport->ifport->pots_transfer) {
688 struct lcr_msg *message;
689 class Pfxs *pots1 = NULL, *pots2 = NULL;
693 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
694 pots = (class Pfxs *)port;
695 if (pots->p_m_mISDNport == mISDNport) {
696 if (pots->p_state == PORT_STATE_CONNECT
697 || pots->p_state == PORT_STATE_IN_PROCEEDING
698 || pots->p_state == PORT_STATE_IN_ALERTING) {
711 if (pots1->p_state == PORT_STATE_CONNECT) {
712 message = message_create(pots1->p_serial, ACTIVE_EPOINT(pots1->p_epointlist), PORT_TO_EPOINT, MESSAGE_TRANSFER);
713 message_put(message);
715 else if (pots2->p_state == PORT_STATE_CONNECT) {
716 message = message_create(pots2->p_serial, ACTIVE_EPOINT(pots2->p_epointlist), PORT_TO_EPOINT, MESSAGE_TRANSFER);
717 message_put(message);
719 pots1->hangup_ind(cont);
720 pots2->hangup_ind(cont);
724 if (mISDNport->ifport->pots_ring) {
725 /* release all except calls on hold, let the latest call ring */
728 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
729 pots = (class Pfxs *)port;
730 if (pots->p_m_mISDNport == mISDNport) {
731 if (pots->p_state == PORT_STATE_CONNECT && pots->p_m_hold) {
732 if (pots->p_m_fxs_age > latest) {
733 latest = pots->p_m_fxs_age;
737 if (pots->p_state == PORT_STATE_OUT_ALERTING)
738 alerting_pots = pots;
745 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
746 pots = (class Pfxs *)port;
747 if (pots->p_m_mISDNport == mISDNport) {
748 if ((pots->p_state != PORT_STATE_CONNECT || !pots->p_m_hold) && pots != alerting_pots) {
749 PDEBUG(DEBUG_ISDN, "Pfxs(%s) release because pots-ring-after-hangup set and call not on hold / alerting\n", pots->p_name);
750 pots->hangup_ind(cont);
757 PDEBUG(DEBUG_ISDN, "Pfxs(%s) answer because pots-ring-after-hangup set and call is alerting (knocking)\n", alerting_pots->p_name);
758 alerting_pots->retrieve_ind(cont);
762 PDEBUG(DEBUG_ISDN, "Pfxs(%s) retrieve because pots-ring-after-hangup set and call is latest on hold\n", latest_pots->p_name);
763 latest_pots->retrieve_ind(cont);
767 /* release all pots */
770 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
771 pots = (class Pfxs *)port;
772 if (pots->p_m_mISDNport == mISDNport) {
773 PDEBUG(DEBUG_ISDN, "Pfxs(%s) release because pots-ring-after-hangup not set\n", pots->p_name);
774 pots->hangup_ind(cont);
781 case POTS_HOOK_FLASH:
784 if (!mISDNport->ifport->pots_flash) {
785 PDEBUG(DEBUG_ISDN, "Pfxs flash key is disabled\n");
788 /* hold active pots / release not active pots */
791 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
792 pots = (class Pfxs *)port;
793 if (pots->p_m_mISDNport == mISDNport) {
794 if (pots->p_state == PORT_STATE_CONNECT) {
795 if (pots->p_m_hold) {
796 if (pots->p_m_fxs_age > latest) {
797 latest = pots->p_m_fxs_age;
801 PDEBUG(DEBUG_ISDN, "Pfxs(%s) hold, because flash on active call\n", pots->p_name);
802 pots->hold_ind(cont);
804 } else if (pots->p_state == PORT_STATE_OUT_ALERTING) {
805 alerting_pots = pots;
807 PDEBUG(DEBUG_ISDN, "Pfxs(%s) hangup, because flash on incomplete/released call\n", pots->p_name);
808 pots->hangup_ind(cont);
815 /* now we have our bchannel available, so we can look alerting port to answer */
817 PDEBUG(DEBUG_ISDN, "Pfxs(%s) answer because call is alerting (knocking)\n", alerting_pots->p_name);
818 alerting_pots->answer_ind(cont);
822 PDEBUG(DEBUG_ISDN, "Pfxs(%s) retrieve because call is latest on hold\n", latest_pots->p_name);
823 latest_pots->retrieve_ind(cont);
830 PERROR("unhandled message: xontrol(0x%x)\n", cont);
836 #endif /* ISDN_P_FXS_POTS */