Import 2.3.10pre5
[davej-history.git] / drivers / isdn / hisax / q931.c
blobd3c269a04db1774d51789eac868a4b7994c5cbf6
1 /* $Id: q931.c,v 1.7 1998/11/15 23:55:17 keil Exp $
3 * q931.c code to decode ITU Q.931 call control messages
5 * Author Jan den Ouden
7 * Changelog
9 * Pauline Middelink general improvements
11 * Beat Doebeli cause texts, display information element
13 * Karsten Keil cause texts, display information element for 1TR6
16 * $Log: q931.c,v $
17 * Revision 1.7 1998/11/15 23:55:17 keil
18 * changes from 2.0
20 * Revision 1.6 1997/07/27 21:09:44 keil
21 * move functions to isdnl3.c
23 * Revision 1.5 1997/04/06 22:56:43 keil
24 * Some cosmetic changes
26 * Revision 1.4 1997/02/09 00:29:11 keil
27 * new interface handling, one interface per card
29 * Revision 1.3 1997/01/21 22:24:59 keil
30 * cleanups
32 * Revision 1.2 1996/10/27 22:12:45 keil
33 * reporting unknown level 3 protocol ids
35 * Revision 1.1 1996/10/13 20:04:56 keil
36 * Initial revision
42 #define __NO_VERSION__
43 #include "hisax.h"
44 #include "l3_1tr6.h"
46 void
47 iecpy(u_char * dest, u_char * iestart, int ieoffset)
49 u_char *p;
50 int l;
52 p = iestart + ieoffset + 2;
53 l = iestart[1] - ieoffset;
54 while (l--)
55 *dest++ = *p++;
56 *dest++ = '\0';
60 * According to Table 4-2/Q.931
62 static
63 struct MessageType {
64 u_char nr;
65 char *descr;
66 } mtlist[] = {
69 0x1, "ALERTING"
72 0x2, "CALL PROCEEDING"
75 0x7, "CONNECT"
78 0xf, "CONNECT ACKNOWLEDGE"
81 0x3, "PROGRESS"
84 0x5, "SETUP"
87 0xd, "SETUP ACKNOWLEDGE"
90 0x26, "RESUME"
93 0x2e, "RESUME ACKNOWLEDGE"
96 0x22, "RESUME REJECT"
99 0x25, "SUSPEND"
102 0x2d, "SUSPEND ACKNOWLEDGE"
105 0x21, "SUSPEND REJECT"
108 0x20, "USER INFORMATION"
111 0x45, "DISCONNECT"
114 0x4d, "RELEASE"
117 0x5a, "RELEASE COMPLETE"
120 0x46, "RESTART"
123 0x4e, "RESTART ACKNOWLEDGE"
126 0x60, "SEGMENT"
129 0x79, "CONGESTION CONTROL"
132 0x7b, "INFORMATION"
135 0x62, "FACILITY"
138 0x6e, "NOTIFY"
141 0x7d, "STATUS"
144 0x75, "STATUS ENQUIRY"
148 #define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
150 static
151 struct MessageType mt_n0[] =
153 {MT_N0_REG_IND, "REGister INDication"},
154 {MT_N0_CANC_IND, "CANCel INDication"},
155 {MT_N0_FAC_STA, "FACility STAtus"},
156 {MT_N0_STA_ACK, "STAtus ACKnowledge"},
157 {MT_N0_STA_REJ, "STAtus REJect"},
158 {MT_N0_FAC_INF, "FACility INFormation"},
159 {MT_N0_INF_ACK, "INFormation ACKnowledge"},
160 {MT_N0_INF_REJ, "INFormation REJect"},
161 {MT_N0_CLOSE, "CLOSE"},
162 {MT_N0_CLO_ACK, "CLOse ACKnowledge"}
165 #define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
167 static
168 struct MessageType mt_n1[] =
170 {MT_N1_ESC, "ESCape"},
171 {MT_N1_ALERT, "ALERT"},
172 {MT_N1_CALL_SENT, "CALL SENT"},
173 {MT_N1_CONN, "CONNect"},
174 {MT_N1_CONN_ACK, "CONNect ACKnowledge"},
175 {MT_N1_SETUP, "SETUP"},
176 {MT_N1_SETUP_ACK, "SETUP ACKnowledge"},
177 {MT_N1_RES, "RESume"},
178 {MT_N1_RES_ACK, "RESume ACKnowledge"},
179 {MT_N1_RES_REJ, "RESume REJect"},
180 {MT_N1_SUSP, "SUSPend"},
181 {MT_N1_SUSP_ACK, "SUSPend ACKnowledge"},
182 {MT_N1_SUSP_REJ, "SUSPend REJect"},
183 {MT_N1_USER_INFO, "USER INFO"},
184 {MT_N1_DET, "DETach"},
185 {MT_N1_DISC, "DISConnect"},
186 {MT_N1_REL, "RELease"},
187 {MT_N1_REL_ACK, "RELease ACKnowledge"},
188 {MT_N1_CANC_ACK, "CANCel ACKnowledge"},
189 {MT_N1_CANC_REJ, "CANCel REJect"},
190 {MT_N1_CON_CON, "CONgestion CONtrol"},
191 {MT_N1_FAC, "FACility"},
192 {MT_N1_FAC_ACK, "FACility ACKnowledge"},
193 {MT_N1_FAC_CAN, "FACility CANcel"},
194 {MT_N1_FAC_REG, "FACility REGister"},
195 {MT_N1_FAC_REJ, "FACility REJect"},
196 {MT_N1_INFO, "INFOrmation"},
197 {MT_N1_REG_ACK, "REGister ACKnowledge"},
198 {MT_N1_REG_REJ, "REGister REJect"},
199 {MT_N1_STAT, "STATus"}
202 #define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
204 static struct MessageType fac_1tr6[] =
206 {FAC_Sperre, "Sperre"},
207 {FAC_Forward1, "Forward 1"},
208 {FAC_Forward2, "Forward 2"},
209 {FAC_Konferenz, "Konferenz"},
210 {FAC_GrabBchan, "Grab Bchannel"},
211 {FAC_Reactivate, "Reactivate"},
212 {FAC_Konferenz3, "Dreier Konferenz"},
213 {FAC_Dienstwechsel1, "Einseitiger Dienstwechsel"},
214 {FAC_Dienstwechsel2, "Zweiseitiger Dienstwechsel"},
215 {FAC_NummernIdent, "Rufnummer-Identifizierung"},
216 {FAC_GBG, "GBG"},
217 {FAC_DisplayUebergeben, "Display Uebergeben"},
218 {FAC_DisplayUmgeleitet, "Display Umgeleitet"},
219 {FAC_Unterdruecke, "Unterdruecke Rufnummer"},
220 {FAC_Deactivate, "Deactivate"},
221 {FAC_Activate, "Activate"},
222 {FAC_SPV, "SPV"},
223 {FAC_Rueckwechsel, "Rueckwechsel"},
224 {FAC_Umleitung, "Umleitung"}
226 #define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
228 static int
229 prbits(char *dest, u_char b, int start, int len)
231 char *dp = dest;
233 b = b << (8 - start);
234 while (len--) {
235 if (b & 0x80)
236 *dp++ = '1';
237 else
238 *dp++ = '0';
239 b = b << 1;
241 return (dp - dest);
244 static
245 u_char *
246 skipext(u_char * p)
248 while (!(*p++ & 0x80));
249 return (p);
253 * Cause Values According to Q.850
254 * edescr: English description
255 * ddescr: German description used by Swissnet II (Swiss Telecom
256 * not yet written...
259 static
260 struct CauseValue {
261 u_char nr;
262 char *edescr;
263 char *ddescr;
264 } cvlist[] = {
267 0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
270 0x02, "No route to specified transit network", ""
273 0x03, "No route to destination", ""
276 0x04, "Send special information tone", ""
279 0x05, "Misdialled trunk prefix", ""
282 0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
285 0x07, "Channel awarded and being delivered in an established channel", ""
288 0x08, "Preemption", ""
291 0x09, "Preemption - circuit reserved for reuse", ""
294 0x10, "Normal call clearing", "Normale Ausloesung"
297 0x11, "User busy", "TNB besetzt"
300 0x12, "No user responding", ""
303 0x13, "No answer from user (user alerted)", ""
306 0x14, "Subscriber absent", ""
309 0x15, "Call rejected", ""
312 0x16, "Number changed", ""
315 0x1a, "non-selected user clearing", ""
318 0x1b, "Destination out of order", ""
321 0x1c, "Invalid number format (address incomplete)", ""
324 0x1d, "Facility rejected", ""
327 0x1e, "Response to Status enquiry", ""
330 0x1f, "Normal, unspecified", ""
333 0x22, "No circuit/channel available", ""
336 0x26, "Network out of order", ""
339 0x27, "Permanent frame mode connection out-of-service", ""
342 0x28, "Permanent frame mode connection operational", ""
345 0x29, "Temporary failure", ""
348 0x2a, "Switching equipment congestion", ""
351 0x2b, "Access information discarded", ""
354 0x2c, "Requested circuit/channel not available", ""
357 0x2e, "Precedence call blocked", ""
360 0x2f, "Resource unavailable, unspecified", ""
363 0x31, "Quality of service unavailable", ""
366 0x32, "Requested facility not subscribed", ""
369 0x35, "Outgoing calls barred within CUG", ""
372 0x37, "Incoming calls barred within CUG", ""
375 0x39, "Bearer capability not authorized", ""
378 0x3a, "Bearer capability not presently available", ""
381 0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
384 0x3f, "Service or option not available, unspecified", ""
387 0x41, "Bearer capability not implemented", ""
390 0x42, "Channel type not implemented", ""
393 0x43, "Requested facility not implemented", ""
396 0x44, "Only restricted digital information bearer capability is available", ""
399 0x4f, "Service or option not implemented", ""
402 0x51, "Invalid call reference value", ""
405 0x52, "Identified channel does not exist", ""
408 0x53, "A suspended call exists, but this call identity does not", ""
411 0x54, "Call identity in use", ""
414 0x55, "No call suspended", ""
417 0x56, "Call having the requested call identity has been cleared", ""
420 0x57, "User not member of CUG", ""
423 0x58, "Incompatible destination", ""
426 0x5a, "Non-existent CUG", ""
429 0x5b, "Invalid transit network selection", ""
432 0x5f, "Invalid message, unspecified", ""
435 0x60, "Mandatory information element is missing", ""
438 0x61, "Message type non-existent or not implemented", ""
441 0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
444 0x63, "Information element/parameter non-existent or not implemented", ""
447 0x64, "Invalid information element contents", ""
450 0x65, "Message not compatible with call state", ""
453 0x66, "Recovery on timer expiry", ""
456 0x67, "Parameter non-existent or not implemented - passed on", ""
459 0x6e, "Message with unrecognized parameter discarded", ""
462 0x6f, "Protocol error, unspecified", ""
465 0x7f, "Interworking, unspecified", ""
469 #define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
471 static
473 prcause(char *dest, u_char * p)
475 u_char *end;
476 char *dp = dest;
477 int i, cause;
479 end = p + p[1] + 1;
480 p += 2;
481 dp += sprintf(dp, " coding ");
482 dp += prbits(dp, *p, 7, 2);
483 dp += sprintf(dp, " location ");
484 dp += prbits(dp, *p, 4, 4);
485 *dp++ = '\n';
486 p = skipext(p);
488 cause = 0x7f & *p++;
490 /* locate cause value */
491 for (i = 0; i < CVSIZE; i++)
492 if (cvlist[i].nr == cause)
493 break;
495 /* display cause value if it exists */
496 if (i == CVSIZE)
497 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
498 else
499 dp += sprintf(dp, " cause value %x : %s \n", cause, cvlist[i].edescr);
501 while (!0) {
502 if (p > end)
503 break;
504 dp += sprintf(dp, " diag attribute %d ", *p++ & 0x7f);
505 dp += sprintf(dp, " rej %d ", *p & 0x7f);
506 if (*p & 0x80) {
507 *dp++ = '\n';
508 break;
509 } else
510 dp += sprintf(dp, " av %d\n", (*++p) & 0x7f);
512 return (dp - dest);
516 static
517 struct MessageType cause_1tr6[] =
519 {CAUSE_InvCRef, "Invalid Call Reference"},
520 {CAUSE_BearerNotImpl, "Bearer Service Not Implemented"},
521 {CAUSE_CIDunknown, "Caller Identity unknown"},
522 {CAUSE_CIDinUse, "Caller Identity in Use"},
523 {CAUSE_NoChans, "No Channels available"},
524 {CAUSE_FacNotImpl, "Facility Not Implemented"},
525 {CAUSE_FacNotSubscr, "Facility Not Subscribed"},
526 {CAUSE_OutgoingBarred, "Outgoing calls barred"},
527 {CAUSE_UserAccessBusy, "User Access Busy"},
528 {CAUSE_NegativeGBG, "Negative GBG"},
529 {CAUSE_UnknownGBG, "Unknown GBG"},
530 {CAUSE_NoSPVknown, "No SPV known"},
531 {CAUSE_DestNotObtain, "Destination not obtainable"},
532 {CAUSE_NumberChanged, "Number changed"},
533 {CAUSE_OutOfOrder, "Out Of Order"},
534 {CAUSE_NoUserResponse, "No User Response"},
535 {CAUSE_UserBusy, "User Busy"},
536 {CAUSE_IncomingBarred, "Incoming Barred"},
537 {CAUSE_CallRejected, "Call Rejected"},
538 {CAUSE_NetworkCongestion, "Network Congestion"},
539 {CAUSE_RemoteUser, "Remote User initiated"},
540 {CAUSE_LocalProcErr, "Local Procedure Error"},
541 {CAUSE_RemoteProcErr, "Remote Procedure Error"},
542 {CAUSE_RemoteUserSuspend, "Remote User Suspend"},
543 {CAUSE_RemoteUserResumed, "Remote User Resumed"},
544 {CAUSE_UserInfoDiscarded, "User Info Discarded"}
547 int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
549 static int
550 prcause_1tr6(char *dest, u_char * p)
552 char *dp = dest;
553 int i, cause;
555 p++;
556 if (0 == *p) {
557 dp += sprintf(dp, " OK (cause length=0)\n");
558 return (dp - dest);
559 } else if (*p > 1) {
560 dp += sprintf(dp, " coding ");
561 dp += prbits(dp, p[2], 7, 2);
562 dp += sprintf(dp, " location ");
563 dp += prbits(dp, p[2], 4, 4);
564 *dp++ = '\n';
566 p++;
567 cause = 0x7f & *p;
569 /* locate cause value */
570 for (i = 0; i < cause_1tr6_len; i++)
571 if (cause_1tr6[i].nr == cause)
572 break;
574 /* display cause value if it exists */
575 if (i == cause_1tr6_len)
576 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
577 else
578 dp += sprintf(dp, " cause value %x : %s \n", cause, cause_1tr6[i].descr);
580 return (dp - dest);
584 static int
585 prchident(char *dest, u_char * p)
587 char *dp = dest;
589 p += 2;
590 dp += sprintf(dp, " octet 3 ");
591 dp += prbits(dp, *p, 8, 8);
592 *dp++ = '\n';
593 return (dp - dest);
596 static int
597 prcalled(char *dest, u_char * p)
599 int l;
600 char *dp = dest;
602 p++;
603 l = *p++ - 1;
604 dp += sprintf(dp, " octet 3 ");
605 dp += prbits(dp, *p++, 8, 8);
606 *dp++ = '\n';
607 dp += sprintf(dp, " number digits ");
608 while (l--)
609 *dp++ = *p++;
610 *dp++ = '\n';
611 return (dp - dest);
613 static int
614 prcalling(char *dest, u_char * p)
616 int l;
617 char *dp = dest;
619 p++;
620 l = *p++ - 1;
621 dp += sprintf(dp, " octet 3 ");
622 dp += prbits(dp, *p, 8, 8);
623 *dp++ = '\n';
624 if (!(*p & 0x80)) {
625 dp += sprintf(dp, " octet 3a ");
626 dp += prbits(dp, *++p, 8, 8);
627 *dp++ = '\n';
628 l--;
630 p++;
632 dp += sprintf(dp, " number digits ");
633 while (l--)
634 *dp++ = *p++;
635 *dp++ = '\n';
636 return (dp - dest);
639 static
641 prbearer(char *dest, u_char * p)
643 char *dp = dest, ch;
645 p += 2;
646 dp += sprintf(dp, " octet 3 ");
647 dp += prbits(dp, *p++, 8, 8);
648 *dp++ = '\n';
649 dp += sprintf(dp, " octet 4 ");
650 dp += prbits(dp, *p, 8, 8);
651 *dp++ = '\n';
652 if ((*p++ & 0x1f) == 0x18) {
653 dp += sprintf(dp, " octet 4.1 ");
654 dp += prbits(dp, *p++, 8, 8);
655 *dp++ = '\n';
657 /* check for user information layer 1 */
658 if ((*p & 0x60) == 0x20) {
659 ch = ' ';
660 do {
661 dp += sprintf(dp, " octet 5%c ", ch);
662 dp += prbits(dp, *p, 8, 8);
663 *dp++ = '\n';
664 if (ch == ' ')
665 ch = 'a';
666 else
667 ch++;
669 while (!(*p++ & 0x80));
671 /* check for user information layer 2 */
672 if ((*p & 0x60) == 0x40) {
673 dp += sprintf(dp, " octet 6 ");
674 dp += prbits(dp, *p++, 8, 8);
675 *dp++ = '\n';
677 /* check for user information layer 3 */
678 if ((*p & 0x60) == 0x60) {
679 dp += sprintf(dp, " octet 7 ");
680 dp += prbits(dp, *p++, 8, 8);
681 *dp++ = '\n';
683 return (dp - dest);
686 static int
687 general(char *dest, u_char * p)
689 char *dp = dest;
690 char ch = ' ';
691 int l, octet = 3;
693 p++;
694 l = *p++;
695 /* Iterate over all octets in the information element */
696 while (l--) {
697 dp += sprintf(dp, " octet %d%c ", octet, ch);
698 dp += prbits(dp, *p++, 8, 8);
699 *dp++ = '\n';
701 /* last octet in group? */
702 if (*p & 0x80) {
703 octet++;
704 ch = ' ';
705 } else if (ch == ' ')
706 ch = 'a';
707 else
708 ch++;
710 return (dp - dest);
713 static int
714 prcharge(char *dest, u_char * p)
716 char *dp = dest;
717 int l;
719 p++;
720 l = *p++ - 1;
721 dp += sprintf(dp, " GEA ");
722 dp += prbits(dp, *p++, 8, 8);
723 dp += sprintf(dp, " Anzahl: ");
724 /* Iterate over all octets in the * information element */
725 while (l--)
726 *dp++ = *p++;
727 *dp++ = '\n';
728 return (dp - dest);
730 static int
731 prtext(char *dest, u_char * p)
733 char *dp = dest;
734 int l;
736 p++;
737 l = *p++;
738 dp += sprintf(dp, " ");
739 /* Iterate over all octets in the * information element */
740 while (l--)
741 *dp++ = *p++;
742 *dp++ = '\n';
743 return (dp - dest);
745 static int
746 display(char *dest, u_char * p)
748 char *dp = dest;
749 char ch = ' ';
750 int l, octet = 3;
752 p++;
753 l = *p++;
754 /* Iterate over all octets in the * display-information element */
755 dp += sprintf(dp, " \"");
756 while (l--) {
757 dp += sprintf(dp, "%c", *p++);
759 /* last octet in group? */
760 if (*p & 0x80) {
761 octet++;
762 ch = ' ';
763 } else if (ch == ' ')
764 ch = 'a';
766 else
767 ch++;
769 *dp++ = '\"';
770 *dp++ = '\n';
771 return (dp - dest);
775 prfacility(char *dest, u_char * p)
777 char *dp = dest;
778 int l, l2;
780 p++;
781 l = *p++;
782 dp += sprintf(dp, " octet 3 ");
783 dp += prbits(dp, *p++, 8, 8);
784 dp += sprintf(dp, "\n");
785 l -= 1;
787 while (l > 0) {
788 dp += sprintf(dp, " octet 4 ");
789 dp += prbits(dp, *p++, 8, 8);
790 dp += sprintf(dp, "\n");
791 dp += sprintf(dp, " octet 5 %d\n", l2 = *p++ & 0x7f);
792 l -= 2;
793 dp += sprintf(dp, " contents ");
794 while (l2--) {
795 dp += sprintf(dp, "%2x ", *p++);
796 l--;
798 dp += sprintf(dp, "\n");
801 return (dp - dest);
804 static
805 struct InformationElement {
806 u_char nr;
807 char *descr;
808 int (*f) (char *, u_char *);
809 } ielist[] = {
812 0x00, "Segmented message", general
815 0x04, "Bearer capability", prbearer
818 0x08, "Cause", prcause
821 0x10, "Call identity", general
824 0x14, "Call state", general
827 0x18, "Channel identification", prchident
830 0x1c, "Facility", prfacility
833 0x1e, "Progress indicator", general
836 0x20, "Network-specific facilities", general
839 0x27, "Notification indicator", general
842 0x28, "Display", display
845 0x29, "Date/Time", general
848 0x2c, "Keypad facility", general
851 0x34, "Signal", general
854 0x40, "Information rate", general
857 0x42, "End-to-end delay", general
860 0x43, "Transit delay selection and indication", general
863 0x44, "Packet layer binary parameters", general
866 0x45, "Packet layer window size", general
869 0x46, "Packet size", general
872 0x47, "Closed user group", general
875 0x4a, "Reverse charge indication", general
878 0x6c, "Calling party number", prcalling
881 0x6d, "Calling party subaddress", general
884 0x70, "Called party number", prcalled
887 0x71, "Called party subaddress", general
890 0x74, "Redirecting number", general
893 0x78, "Transit network selection", general
896 0x79, "Restart indicator", general
899 0x7c, "Low layer compatibility", general
902 0x7d, "High layer compatibility", general
905 0x7e, "User-user", general
908 0x7f, "Escape for extension", general
913 #define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
915 static struct InformationElement we_0[] =
917 {WE0_cause, "Cause", prcause_1tr6},
918 {WE0_connAddr, "Connecting Address", prcalled},
919 {WE0_callID, "Call IDentity", general},
920 {WE0_chanID, "Channel IDentity", general},
921 {WE0_netSpecFac, "Network Specific Facility", general},
922 {WE0_display, "Display", general},
923 {WE0_keypad, "Keypad", general},
924 {WE0_origAddr, "Origination Address", prcalled},
925 {WE0_destAddr, "Destination Address", prcalled},
926 {WE0_userInfo, "User Info", general}
929 #define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
931 static struct InformationElement we_6[] =
933 {WE6_serviceInd, "Service Indicator", general},
934 {WE6_chargingInfo, "Charging Information", prcharge},
935 {WE6_date, "Date", prtext},
936 {WE6_facSelect, "Facility Select", general},
937 {WE6_facStatus, "Facility Status", general},
938 {WE6_statusCalled, "Status Called", general},
939 {WE6_addTransAttr, "Additional Transmission Attributes", general}
941 #define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
944 QuickHex(char *txt, u_char * p, int cnt)
946 register int i;
947 register char *t = txt;
948 register u_char w;
950 for (i = 0; i < cnt; i++) {
951 *t++ = ' ';
952 w = (p[i] >> 4) & 0x0f;
953 if (w < 10)
954 *t++ = '0' + w;
955 else
956 *t++ = 'A' - 10 + w;
957 w = p[i] & 0x0f;
958 if (w < 10)
959 *t++ = '0' + w;
960 else
961 *t++ = 'A' - 10 + w;
963 *t++ = 0;
964 return (t - txt);
967 void
968 LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
970 char *dp;
972 if (size < 1)
973 return;
974 dp = cs->dlog;
975 if (size < MAX_DLOG_SPACE / 3 - 10) {
976 *dp++ = 'H';
977 *dp++ = 'E';
978 *dp++ = 'X';
979 *dp++ = ':';
980 dp += QuickHex(dp, buf, size);
981 dp--;
982 *dp++ = '\n';
983 *dp = 0;
984 HiSax_putstatus(cs, NULL, cs->dlog);
985 } else
986 HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
989 void
990 dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
992 u_char *bend, *buf;
993 char *dp;
994 unsigned char pd, cr_l, cr, mt;
995 unsigned char sapi, tei, ftyp;
996 int i, cset = 0, cs_old = 0, cs_fest = 0;
997 int size, finish = 0;
999 if (skb->len < 3)
1000 return;
1001 /* display header */
1002 dp = cs->dlog;
1003 dp += jiftime(dp, jiffies);
1004 *dp++ = ' ';
1005 sapi = skb->data[0] >> 2;
1006 tei = skb->data[1] >> 1;
1007 ftyp = skb->data[2];
1008 buf = skb->data;
1009 dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
1010 size = skb->len;
1012 if (tei == GROUP_TEI) {
1013 if (sapi == CTRL_SAPI) { /* sapi 0 */
1014 if (ftyp == 3) {
1015 dp += sprintf(dp, "broadcast\n");
1016 buf += 3;
1017 size -= 3;
1018 } else {
1019 dp += sprintf(dp, "no UI broadcast\n");
1020 finish = 1;
1022 } else if (sapi == TEI_SAPI) {
1023 dp += sprintf(dp, "tei managment\n");
1024 finish = 1;
1025 } else {
1026 dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
1027 finish = 1;
1029 } else {
1030 if (sapi == CTRL_SAPI) {
1031 if (!(ftyp & 1)) { /* IFrame */
1032 dp += sprintf(dp, "with tei %d\n", tei);
1033 buf += 4;
1034 size -= 4;
1035 } else {
1036 dp += sprintf(dp, "SFrame with tei %d\n", tei);
1037 finish = 1;
1039 } else {
1040 dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
1041 finish = 1;
1044 bend = skb->data + skb->len;
1045 if (buf >= bend) {
1046 dp += sprintf(dp, "frame too short\n");
1047 finish = 1;
1049 if (finish) {
1050 *dp = 0;
1051 HiSax_putstatus(cs, NULL, cs->dlog);
1052 return;
1054 if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */
1055 /* locate message type */
1056 pd = *buf++;
1057 cr_l = *buf++;
1058 if (cr_l)
1059 cr = *buf++;
1060 else
1061 cr = 0;
1062 mt = *buf++;
1063 if (pd == PROTO_DIS_N0) { /* N0 */
1064 for (i = 0; i < MT_N0_LEN; i++)
1065 if (mt_n0[i].nr == mt)
1066 break;
1067 /* display message type if it exists */
1068 if (i == MT_N0_LEN)
1069 dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
1070 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1071 size, mt);
1072 else
1073 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1074 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1075 size, mt_n0[i].descr);
1076 } else { /* N1 */
1077 for (i = 0; i < MT_N1_LEN; i++)
1078 if (mt_n1[i].nr == mt)
1079 break;
1080 /* display message type if it exists */
1081 if (i == MT_N1_LEN)
1082 dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
1083 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1084 size, mt);
1085 else
1086 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1087 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1088 size, mt_n1[i].descr);
1091 /* display each information element */
1092 while (buf < bend) {
1093 /* Is it a single octet information element? */
1094 if (*buf & 0x80) {
1095 switch ((*buf >> 4) & 7) {
1096 case 1:
1097 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1098 cs_old = cset;
1099 cset = *buf & 7;
1100 cs_fest = *buf & 8;
1101 break;
1102 case 3:
1103 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1104 break;
1105 case 2:
1106 if (*buf == 0xa0) {
1107 dp += sprintf(dp, " More data\n");
1108 break;
1110 if (*buf == 0xa1) {
1111 dp += sprintf(dp, " Sending complete\n");
1113 break;
1114 /* fall through */
1115 default:
1116 dp += sprintf(dp, " Reserved %x\n", *buf);
1117 break;
1119 buf++;
1120 continue;
1122 /* No, locate it in the table */
1123 if (cset == 0) {
1124 for (i = 0; i < WE_0_LEN; i++)
1125 if (*buf == we_0[i].nr)
1126 break;
1128 /* When found, give appropriate msg */
1129 if (i != WE_0_LEN) {
1130 dp += sprintf(dp, " %s\n", we_0[i].descr);
1131 dp += we_0[i].f(dp, buf);
1132 } else
1133 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1134 } else if (cset == 6) {
1135 for (i = 0; i < WE_6_LEN; i++)
1136 if (*buf == we_6[i].nr)
1137 break;
1139 /* When found, give appropriate msg */
1140 if (i != WE_6_LEN) {
1141 dp += sprintf(dp, " %s\n", we_6[i].descr);
1142 dp += we_6[i].f(dp, buf);
1143 } else
1144 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1145 } else
1146 dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1147 /* Skip to next element */
1148 if (cs_fest == 8) {
1149 cset = cs_old;
1150 cs_old = 0;
1151 cs_fest = 0;
1153 buf += buf[1] + 2;
1155 } else if (buf[0] == 8) { /* EURO */
1156 /* locate message type */
1157 buf++;
1158 cr_l = *buf++;
1159 if (cr_l)
1160 cr = *buf++;
1161 else
1162 cr = 0;
1163 mt = *buf++;
1164 for (i = 0; i < MTSIZE; i++)
1165 if (mtlist[i].nr == mt)
1166 break;
1168 /* display message type if it exists */
1169 if (i == MTSIZE)
1170 dp += sprintf(dp, "callref %d %s size %d unknown message type %x!\n",
1171 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1172 size, mt);
1173 else
1174 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1175 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1176 size, mtlist[i].descr);
1178 /* display each information element */
1179 while (buf < bend) {
1180 /* Is it a single octet information element? */
1181 if (*buf & 0x80) {
1182 switch ((*buf >> 4) & 7) {
1183 case 1:
1184 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1185 break;
1186 case 3:
1187 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1188 break;
1189 case 5:
1190 dp += sprintf(dp, " Repeat indicator %x\n", *buf & 0xf);
1191 break;
1192 case 2:
1193 if (*buf == 0xa0) {
1194 dp += sprintf(dp, " More data\n");
1195 break;
1197 if (*buf == 0xa1) {
1198 dp += sprintf(dp, " Sending complete\n");
1200 break;
1201 /* fall through */
1202 default:
1203 dp += sprintf(dp, " Reserved %x\n", *buf);
1204 break;
1206 buf++;
1207 continue;
1209 /* No, locate it in the table */
1210 for (i = 0; i < IESIZE; i++)
1211 if (*buf == ielist[i].nr)
1212 break;
1214 /* When not found, give appropriate msg */
1215 if (i != IESIZE) {
1216 dp += sprintf(dp, " %s\n", ielist[i].descr);
1217 dp += ielist[i].f(dp, buf);
1218 } else
1219 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1221 /* Skip to next element */
1222 buf += buf[1] + 2;
1224 } else {
1225 dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
1227 *dp = 0;
1228 HiSax_putstatus(cs, NULL, cs->dlog);