q931.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:31k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: q931.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
  2.  *
  3.  * code to decode ITU Q.931 call control messages
  4.  *
  5.  * Author       Jan den Ouden
  6.  * Copyright    by Jan den Ouden
  7.  *
  8.  * This software may be used and distributed according to the terms
  9.  * of the GNU General Public License, incorporated herein by reference.
  10.  *
  11.  * Changelog:
  12.  *
  13.  * Pauline Middelink    general improvements
  14.  * Beat Doebeli         cause texts, display information element
  15.  * Karsten Keil         cause texts, display information element for 1TR6
  16.  *
  17.  */
  18. #define __NO_VERSION__
  19. #include "hisax.h"
  20. #include "l3_1tr6.h"
  21. void
  22. iecpy(u_char * dest, u_char * iestart, int ieoffset)
  23. {
  24. u_char *p;
  25. int l;
  26. p = iestart + ieoffset + 2;
  27. l = iestart[1] - ieoffset;
  28. while (l--)
  29. *dest++ = *p++;
  30. *dest++ = '';
  31. }
  32. /*
  33.  * According to Table 4-2/Q.931
  34.  */
  35. static
  36. struct MessageType {
  37. u_char nr;
  38. char *descr;
  39. } mtlist[] = {
  40. {
  41. 0x1, "ALERTING"
  42. },
  43. {
  44. 0x2, "CALL PROCEEDING"
  45. },
  46. {
  47. 0x7, "CONNECT"
  48. },
  49. {
  50. 0xf, "CONNECT ACKNOWLEDGE"
  51. },
  52. {
  53. 0x3, "PROGRESS"
  54. },
  55. {
  56. 0x5, "SETUP"
  57. },
  58. {
  59. 0xd, "SETUP ACKNOWLEDGE"
  60. },
  61. {
  62. 0x24, "HOLD"
  63. },
  64. {
  65. 0x28, "HOLD ACKNOWLEDGE"
  66. },
  67. {
  68. 0x30, "HOLD REJECT"
  69. },
  70. {
  71. 0x31, "RETRIEVE"
  72. },
  73. {
  74. 0x33, "RETRIEVE ACKNOWLEDGE"
  75. },
  76. {
  77. 0x37, "RETRIEVE REJECT"
  78. },
  79. {
  80. 0x26, "RESUME"
  81. },
  82. {
  83. 0x2e, "RESUME ACKNOWLEDGE"
  84. },
  85. {
  86. 0x22, "RESUME REJECT"
  87. },
  88. {
  89. 0x25, "SUSPEND"
  90. },
  91. {
  92. 0x2d, "SUSPEND ACKNOWLEDGE"
  93. },
  94. {
  95. 0x21, "SUSPEND REJECT"
  96. },
  97. {
  98. 0x20, "USER INFORMATION"
  99. },
  100. {
  101. 0x45, "DISCONNECT"
  102. },
  103. {
  104. 0x4d, "RELEASE"
  105. },
  106. {
  107. 0x5a, "RELEASE COMPLETE"
  108. },
  109. {
  110. 0x46, "RESTART"
  111. },
  112. {
  113. 0x4e, "RESTART ACKNOWLEDGE"
  114. },
  115. {
  116. 0x60, "SEGMENT"
  117. },
  118. {
  119. 0x79, "CONGESTION CONTROL"
  120. },
  121. {
  122. 0x7b, "INFORMATION"
  123. },
  124. {
  125. 0x62, "FACILITY"
  126. },
  127. {
  128. 0x6e, "NOTIFY"
  129. },
  130. {
  131. 0x7d, "STATUS"
  132. },
  133. {
  134. 0x75, "STATUS ENQUIRY"
  135. }
  136. };
  137. #define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
  138. static
  139. struct MessageType mt_n0[] =
  140. {
  141. {MT_N0_REG_IND, "REGister INDication"},
  142. {MT_N0_CANC_IND, "CANCel INDication"},
  143. {MT_N0_FAC_STA, "FACility STAtus"},
  144. {MT_N0_STA_ACK, "STAtus ACKnowledge"},
  145. {MT_N0_STA_REJ, "STAtus REJect"},
  146. {MT_N0_FAC_INF, "FACility INFormation"},
  147. {MT_N0_INF_ACK, "INFormation ACKnowledge"},
  148. {MT_N0_INF_REJ, "INFormation REJect"},
  149. {MT_N0_CLOSE, "CLOSE"},
  150. {MT_N0_CLO_ACK, "CLOse ACKnowledge"}
  151. };
  152. #define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
  153. static
  154. struct MessageType mt_n1[] =
  155. {
  156. {MT_N1_ESC, "ESCape"},
  157. {MT_N1_ALERT, "ALERT"},
  158. {MT_N1_CALL_SENT, "CALL SENT"},
  159. {MT_N1_CONN, "CONNect"},
  160. {MT_N1_CONN_ACK, "CONNect ACKnowledge"},
  161. {MT_N1_SETUP, "SETUP"},
  162. {MT_N1_SETUP_ACK, "SETUP ACKnowledge"},
  163. {MT_N1_RES, "RESume"},
  164. {MT_N1_RES_ACK, "RESume ACKnowledge"},
  165. {MT_N1_RES_REJ, "RESume REJect"},
  166. {MT_N1_SUSP, "SUSPend"},
  167. {MT_N1_SUSP_ACK, "SUSPend ACKnowledge"},
  168. {MT_N1_SUSP_REJ, "SUSPend REJect"},
  169. {MT_N1_USER_INFO, "USER INFO"},
  170. {MT_N1_DET, "DETach"},
  171. {MT_N1_DISC, "DISConnect"},
  172. {MT_N1_REL, "RELease"},
  173. {MT_N1_REL_ACK, "RELease ACKnowledge"},
  174. {MT_N1_CANC_ACK, "CANCel ACKnowledge"},
  175. {MT_N1_CANC_REJ, "CANCel REJect"},
  176. {MT_N1_CON_CON, "CONgestion CONtrol"},
  177. {MT_N1_FAC, "FACility"},
  178. {MT_N1_FAC_ACK, "FACility ACKnowledge"},
  179. {MT_N1_FAC_CAN, "FACility CANcel"},
  180. {MT_N1_FAC_REG, "FACility REGister"},
  181. {MT_N1_FAC_REJ, "FACility REJect"},
  182. {MT_N1_INFO, "INFOrmation"},
  183. {MT_N1_REG_ACK, "REGister ACKnowledge"},
  184. {MT_N1_REG_REJ, "REGister REJect"},
  185. {MT_N1_STAT, "STATus"}
  186. };
  187. #define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
  188. static int
  189. prbits(char *dest, u_char b, int start, int len)
  190. {
  191. char *dp = dest;
  192. b = b << (8 - start);
  193. while (len--) {
  194. if (b & 0x80)
  195. *dp++ = '1';
  196. else
  197. *dp++ = '0';
  198. b = b << 1;
  199. }
  200. return (dp - dest);
  201. }
  202. static
  203. u_char *
  204. skipext(u_char * p)
  205. {
  206. while (!(*p++ & 0x80));
  207. return (p);
  208. }
  209. /*
  210.  * Cause Values According to Q.850
  211.  * edescr: English description
  212.  * ddescr: German description used by Swissnet II (Swiss Telecom
  213.  *         not yet written...
  214.  */
  215. static
  216. struct CauseValue {
  217. u_char nr;
  218. char *edescr;
  219. char *ddescr;
  220. } cvlist[] = {
  221. {
  222. 0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
  223. },
  224. {
  225. 0x02, "No route to specified transit network", ""
  226. },
  227. {
  228. 0x03, "No route to destination", ""
  229. },
  230. {
  231. 0x04, "Send special information tone", ""
  232. },
  233. {
  234. 0x05, "Misdialled trunk prefix", ""
  235. },
  236. {
  237. 0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
  238. },
  239. {
  240. 0x07, "Channel awarded and being delivered in an established channel", ""
  241. },
  242. {
  243. 0x08, "Preemption", ""
  244. },
  245. {
  246. 0x09, "Preemption - circuit reserved for reuse", ""
  247. },
  248. {
  249. 0x10, "Normal call clearing", "Normale Ausloesung"
  250. },
  251. {
  252. 0x11, "User busy", "TNB besetzt"
  253. },
  254. {
  255. 0x12, "No user responding", ""
  256. },
  257. {
  258. 0x13, "No answer from user (user alerted)", ""
  259. },
  260. {
  261. 0x14, "Subscriber absent", ""
  262. },
  263. {
  264. 0x15, "Call rejected", ""
  265. },
  266. {
  267. 0x16, "Number changed", ""
  268. },
  269. {
  270. 0x1a, "non-selected user clearing", ""
  271. },
  272. {
  273. 0x1b, "Destination out of order", ""
  274. },
  275. {
  276. 0x1c, "Invalid number format (address incomplete)", ""
  277. },
  278. {
  279. 0x1d, "Facility rejected", ""
  280. },
  281. {
  282. 0x1e, "Response to Status enquiry", ""
  283. },
  284. {
  285. 0x1f, "Normal, unspecified", ""
  286. },
  287. {
  288. 0x22, "No circuit/channel available", ""
  289. },
  290. {
  291. 0x26, "Network out of order", ""
  292. },
  293. {
  294. 0x27, "Permanent frame mode connection out-of-service", ""
  295. },
  296. {
  297. 0x28, "Permanent frame mode connection operational", ""
  298. },
  299. {
  300. 0x29, "Temporary failure", ""
  301. },
  302. {
  303. 0x2a, "Switching equipment congestion", ""
  304. },
  305. {
  306. 0x2b, "Access information discarded", ""
  307. },
  308. {
  309. 0x2c, "Requested circuit/channel not available", ""
  310. },
  311. {
  312. 0x2e, "Precedence call blocked", ""
  313. },
  314. {
  315. 0x2f, "Resource unavailable, unspecified", ""
  316. },
  317. {
  318. 0x31, "Quality of service unavailable", ""
  319. },
  320. {
  321. 0x32, "Requested facility not subscribed", ""
  322. },
  323. {
  324. 0x35, "Outgoing calls barred within CUG", ""
  325. },
  326. {
  327. 0x37, "Incoming calls barred within CUG", ""
  328. },
  329. {
  330. 0x39, "Bearer capability not authorized", ""
  331. },
  332. {
  333. 0x3a, "Bearer capability not presently available", ""
  334. },
  335. {
  336. 0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
  337. },
  338. {
  339. 0x3f, "Service or option not available, unspecified", ""
  340. },
  341. {
  342. 0x41, "Bearer capability not implemented", ""
  343. },
  344. {
  345. 0x42, "Channel type not implemented", ""
  346. },
  347. {
  348. 0x43, "Requested facility not implemented", ""
  349. },
  350. {
  351. 0x44, "Only restricted digital information bearer capability is available", ""
  352. },
  353. {
  354. 0x4f, "Service or option not implemented", ""
  355. },
  356. {
  357. 0x51, "Invalid call reference value", ""
  358. },
  359. {
  360. 0x52, "Identified channel does not exist", ""
  361. },
  362. {
  363. 0x53, "A suspended call exists, but this call identity does not", ""
  364. },
  365. {
  366. 0x54, "Call identity in use", ""
  367. },
  368. {
  369. 0x55, "No call suspended", ""
  370. },
  371. {
  372. 0x56, "Call having the requested call identity has been cleared", ""
  373. },
  374. {
  375. 0x57, "User not member of CUG", ""
  376. },
  377. {
  378. 0x58, "Incompatible destination", ""
  379. },
  380. {
  381. 0x5a, "Non-existent CUG", ""
  382. },
  383. {
  384. 0x5b, "Invalid transit network selection", ""
  385. },
  386. {
  387. 0x5f, "Invalid message, unspecified", ""
  388. },
  389. {
  390. 0x60, "Mandatory information element is missing", ""
  391. },
  392. {
  393. 0x61, "Message type non-existent or not implemented", ""
  394. },
  395. {
  396. 0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
  397. },
  398. {
  399. 0x63, "Information element/parameter non-existent or not implemented", ""
  400. },
  401. {
  402. 0x64, "Invalid information element contents", ""
  403. },
  404. {
  405. 0x65, "Message not compatible with call state", ""
  406. },
  407. {
  408. 0x66, "Recovery on timer expiry", ""
  409. },
  410. {
  411. 0x67, "Parameter non-existent or not implemented - passed on", ""
  412. },
  413. {
  414. 0x6e, "Message with unrecognized parameter discarded", ""
  415. },
  416. {
  417. 0x6f, "Protocol error, unspecified", ""
  418. },
  419. {
  420. 0x7f, "Interworking, unspecified", ""
  421. },
  422. };
  423. #define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
  424. static
  425. int
  426. prcause(char *dest, u_char * p)
  427. {
  428. u_char *end;
  429. char *dp = dest;
  430. int i, cause;
  431. end = p + p[1] + 1;
  432. p += 2;
  433. dp += sprintf(dp, "    coding ");
  434. dp += prbits(dp, *p, 7, 2);
  435. dp += sprintf(dp, " location ");
  436. dp += prbits(dp, *p, 4, 4);
  437. *dp++ = 'n';
  438. p = skipext(p);
  439. cause = 0x7f & *p++;
  440. /* locate cause value */
  441. for (i = 0; i < CVSIZE; i++)
  442. if (cvlist[i].nr == cause)
  443. break;
  444. /* display cause value if it exists */
  445. if (i == CVSIZE)
  446. dp += sprintf(dp, "Unknown cause type %x!n", cause);
  447. else
  448. dp += sprintf(dp, "  cause value %x : %s n", cause, cvlist[i].edescr);
  449. while (!0) {
  450. if (p > end)
  451. break;
  452. dp += sprintf(dp, "    diag attribute %d ", *p++ & 0x7f);
  453. dp += sprintf(dp, " rej %d ", *p & 0x7f);
  454. if (*p & 0x80) {
  455. *dp++ = 'n';
  456. break;
  457. } else
  458. dp += sprintf(dp, " av %dn", (*++p) & 0x7f);
  459. }
  460. return (dp - dest);
  461. }
  462. static
  463. struct MessageType cause_1tr6[] =
  464. {
  465. {CAUSE_InvCRef, "Invalid Call Reference"},
  466. {CAUSE_BearerNotImpl, "Bearer Service Not Implemented"},
  467. {CAUSE_CIDunknown, "Caller Identity unknown"},
  468. {CAUSE_CIDinUse, "Caller Identity in Use"},
  469. {CAUSE_NoChans, "No Channels available"},
  470. {CAUSE_FacNotImpl, "Facility Not Implemented"},
  471. {CAUSE_FacNotSubscr, "Facility Not Subscribed"},
  472. {CAUSE_OutgoingBarred, "Outgoing calls barred"},
  473. {CAUSE_UserAccessBusy, "User Access Busy"},
  474. {CAUSE_NegativeGBG, "Negative GBG"},
  475. {CAUSE_UnknownGBG, "Unknown  GBG"},
  476. {CAUSE_NoSPVknown, "No SPV known"},
  477. {CAUSE_DestNotObtain, "Destination not obtainable"},
  478. {CAUSE_NumberChanged, "Number changed"},
  479. {CAUSE_OutOfOrder, "Out Of Order"},
  480. {CAUSE_NoUserResponse, "No User Response"},
  481. {CAUSE_UserBusy, "User Busy"},
  482. {CAUSE_IncomingBarred, "Incoming Barred"},
  483. {CAUSE_CallRejected, "Call Rejected"},
  484. {CAUSE_NetworkCongestion, "Network Congestion"},
  485. {CAUSE_RemoteUser, "Remote User initiated"},
  486. {CAUSE_LocalProcErr, "Local Procedure Error"},
  487. {CAUSE_RemoteProcErr, "Remote Procedure Error"},
  488. {CAUSE_RemoteUserSuspend, "Remote User Suspend"},
  489. {CAUSE_RemoteUserResumed, "Remote User Resumed"},
  490. {CAUSE_UserInfoDiscarded, "User Info Discarded"}
  491. };
  492. int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
  493. static int
  494. prcause_1tr6(char *dest, u_char * p)
  495. {
  496. char *dp = dest;
  497. int i, cause;
  498. p++;
  499. if (0 == *p) {
  500. dp += sprintf(dp, "   OK (cause length=0)n");
  501. return (dp - dest);
  502. } else if (*p > 1) {
  503. dp += sprintf(dp, "    coding ");
  504. dp += prbits(dp, p[2], 7, 2);
  505. dp += sprintf(dp, " location ");
  506. dp += prbits(dp, p[2], 4, 4);
  507. *dp++ = 'n';
  508. }
  509. p++;
  510. cause = 0x7f & *p;
  511. /* locate cause value */
  512. for (i = 0; i < cause_1tr6_len; i++)
  513. if (cause_1tr6[i].nr == cause)
  514. break;
  515. /* display cause value if it exists */
  516. if (i == cause_1tr6_len)
  517. dp += sprintf(dp, "Unknown cause type %x!n", cause);
  518. else
  519. dp += sprintf(dp, "  cause value %x : %s n", cause, cause_1tr6[i].descr);
  520. return (dp - dest);
  521. }
  522. static int
  523. prchident(char *dest, u_char * p)
  524. {
  525. char *dp = dest;
  526. p += 2;
  527. dp += sprintf(dp, "    octet 3 ");
  528. dp += prbits(dp, *p, 8, 8);
  529. *dp++ = 'n';
  530. return (dp - dest);
  531. }
  532. static int
  533. prcalled(char *dest, u_char * p)
  534. {
  535. int l;
  536. char *dp = dest;
  537. p++;
  538. l = *p++ - 1;
  539. dp += sprintf(dp, "    octet 3 ");
  540. dp += prbits(dp, *p++, 8, 8);
  541. *dp++ = 'n';
  542. dp += sprintf(dp, "    number digits ");
  543. while (l--)
  544. *dp++ = *p++;
  545. *dp++ = 'n';
  546. return (dp - dest);
  547. }
  548. static int
  549. prcalling(char *dest, u_char * p)
  550. {
  551. int l;
  552. char *dp = dest;
  553. p++;
  554. l = *p++ - 1;
  555. dp += sprintf(dp, "    octet 3 ");
  556. dp += prbits(dp, *p, 8, 8);
  557. *dp++ = 'n';
  558. if (!(*p & 0x80)) {
  559. dp += sprintf(dp, "    octet 3a ");
  560. dp += prbits(dp, *++p, 8, 8);
  561. *dp++ = 'n';
  562. l--;
  563. };
  564. p++;
  565. dp += sprintf(dp, "    number digits ");
  566. while (l--)
  567. *dp++ = *p++;
  568. *dp++ = 'n';
  569. return (dp - dest);
  570. }
  571. static
  572. int
  573. prbearer(char *dest, u_char * p)
  574. {
  575. char *dp = dest, ch;
  576. p += 2;
  577. dp += sprintf(dp, "    octet 3  ");
  578. dp += prbits(dp, *p++, 8, 8);
  579. *dp++ = 'n';
  580. dp += sprintf(dp, "    octet 4  ");
  581. dp += prbits(dp, *p, 8, 8);
  582. *dp++ = 'n';
  583. if ((*p++ & 0x1f) == 0x18) {
  584. dp += sprintf(dp, "    octet 4.1 ");
  585. dp += prbits(dp, *p++, 8, 8);
  586. *dp++ = 'n';
  587. }
  588. /* check for user information layer 1 */
  589. if ((*p & 0x60) == 0x20) {
  590. ch = ' ';
  591. do {
  592. dp += sprintf(dp, "    octet 5%c ", ch);
  593. dp += prbits(dp, *p, 8, 8);
  594. *dp++ = 'n';
  595. if (ch == ' ')
  596. ch = 'a';
  597. else
  598. ch++;
  599. }
  600. while (!(*p++ & 0x80));
  601. }
  602. /* check for user information layer 2 */
  603. if ((*p & 0x60) == 0x40) {
  604. dp += sprintf(dp, "    octet 6  ");
  605. dp += prbits(dp, *p++, 8, 8);
  606. *dp++ = 'n';
  607. }
  608. /* check for user information layer 3 */
  609. if ((*p & 0x60) == 0x60) {
  610. dp += sprintf(dp, "    octet 7  ");
  611. dp += prbits(dp, *p++, 8, 8);
  612. *dp++ = 'n';
  613. }
  614. return (dp - dest);
  615. }
  616. static
  617. int
  618. prbearer_ni1(char *dest, u_char * p)
  619. {
  620. char *dp = dest;
  621. u_char len;
  622. p++;
  623. len = *p++;
  624. dp += sprintf(dp, "    octet 3  ");
  625. dp += prbits(dp, *p, 8, 8);
  626. switch (*p++) {
  627. case 0x80:
  628. dp += sprintf(dp, " Speech");
  629. break;
  630. case 0x88:
  631. dp += sprintf(dp, " Unrestricted digital information");
  632. break;
  633. case 0x90:
  634. dp += sprintf(dp, " 3.1 kHz audio");
  635. break;
  636. default:
  637. dp += sprintf(dp, " Unknown information-transfer capability");
  638. }
  639. *dp++ = 'n';
  640. dp += sprintf(dp, "    octet 4  ");
  641. dp += prbits(dp, *p, 8, 8);
  642. switch (*p++) {
  643. case 0x90:
  644. dp += sprintf(dp, " 64 kbps, circuit mode");
  645. break;
  646. case 0xc0:
  647. dp += sprintf(dp, " Packet mode");
  648. break;
  649. default:
  650. dp += sprintf(dp, " Unknown transfer mode");
  651. }
  652. *dp++ = 'n';
  653. if (len > 2) {
  654. dp += sprintf(dp, "    octet 5  ");
  655. dp += prbits(dp, *p, 8, 8);
  656. switch (*p++) {
  657. case 0x21:
  658. dp += sprintf(dp, " Rate adaptionn");
  659. dp += sprintf(dp, "    octet 5a ");
  660. dp += prbits(dp, *p, 8, 8);
  661. break;
  662. case 0xa2:
  663. dp += sprintf(dp, " u-law");
  664. break;
  665. default:
  666. dp += sprintf(dp, " Unknown UI layer 1 protocol");
  667. }
  668. *dp++ = 'n';
  669. }
  670. return (dp - dest);
  671. }
  672. static int
  673. general(char *dest, u_char * p)
  674. {
  675. char *dp = dest;
  676. char ch = ' ';
  677. int l, octet = 3;
  678. p++;
  679. l = *p++;
  680. /* Iterate over all octets in the information element */
  681. while (l--) {
  682. dp += sprintf(dp, "    octet %d%c ", octet, ch);
  683. dp += prbits(dp, *p++, 8, 8);
  684. *dp++ = 'n';
  685. /* last octet in group? */
  686. if (*p & 0x80) {
  687. octet++;
  688. ch = ' ';
  689. } else if (ch == ' ')
  690. ch = 'a';
  691. else
  692. ch++;
  693. }
  694. return (dp - dest);
  695. }
  696. static int
  697. general_ni1(char *dest, u_char * p)
  698. {
  699. char *dp = dest;
  700. char ch = ' ';
  701. int l, octet = 3;
  702. p++;
  703. l = *p++;
  704. /* Iterate over all octets in the information element */
  705. while (l--) {
  706. dp += sprintf(dp, "    octet %d%c ", octet, ch);
  707. dp += prbits(dp, *p, 8, 8);
  708. *dp++ = 'n';
  709. /* last octet in group? */
  710. if (*p++ & 0x80) {
  711. octet++;
  712. ch = ' ';
  713. } else if (ch == ' ')
  714. ch = 'a';
  715. else
  716. ch++;
  717. }
  718. return (dp - dest);
  719. }
  720. static int
  721. prcharge(char *dest, u_char * p)
  722. {
  723. char *dp = dest;
  724. int l;
  725. p++;
  726. l = *p++ - 1;
  727. dp += sprintf(dp, "    GEA ");
  728. dp += prbits(dp, *p++, 8, 8);
  729. dp += sprintf(dp, "  Anzahl: ");
  730. /* Iterate over all octets in the * information element */
  731. while (l--)
  732. *dp++ = *p++;
  733. *dp++ = 'n';
  734. return (dp - dest);
  735. }
  736. static int
  737. prtext(char *dest, u_char * p)
  738. {
  739. char *dp = dest;
  740. int l;
  741. p++;
  742. l = *p++;
  743. dp += sprintf(dp, "    ");
  744. /* Iterate over all octets in the * information element */
  745. while (l--)
  746. *dp++ = *p++;
  747. *dp++ = 'n';
  748. return (dp - dest);
  749. }
  750. static int
  751. prfeatureind(char *dest, u_char * p)
  752. {
  753. char *dp = dest;
  754. p += 2; /* skip id, len */
  755. dp += sprintf(dp, "    octet 3  ");
  756. dp += prbits(dp, *p, 8, 8);
  757. *dp++ = 'n';
  758. if (!(*p++ & 80)) {
  759. dp += sprintf(dp, "    octet 4  ");
  760. dp += prbits(dp, *p++, 8, 8);
  761. *dp++ = 'n';
  762. }
  763. dp += sprintf(dp, "    Status:  ");
  764. switch (*p) {
  765. case 0:
  766. dp += sprintf(dp, "Idle");
  767. break;
  768. case 1:
  769. dp += sprintf(dp, "Active");
  770. break;
  771. case 2:
  772. dp += sprintf(dp, "Prompt");
  773. break;
  774. case 3:
  775. dp += sprintf(dp, "Pending");
  776. break;
  777. default:
  778. dp += sprintf(dp, "(Reserved)");
  779. break;
  780. }
  781. *dp++ = 'n';
  782. return (dp - dest);
  783. }
  784. static
  785. struct DTag { /* Display tags */
  786. u_char nr;
  787. char *descr;
  788. } dtaglist[] = {
  789. { 0x82, "Continuation" },
  790. { 0x83, "Called address" },
  791. { 0x84, "Cause" },
  792. { 0x85, "Progress indicator" },
  793. { 0x86, "Notification indicator" },
  794. { 0x87, "Prompt" },
  795. { 0x88, "Accumlated digits" },
  796. { 0x89, "Status" },
  797. { 0x8a, "Inband" },
  798. { 0x8b, "Calling address" },
  799. { 0x8c, "Reason" },
  800. { 0x8d, "Calling party name" },
  801. { 0x8e, "Called party name" },
  802. { 0x8f, "Orignal called name" },
  803. { 0x90, "Redirecting name" },
  804. { 0x91, "Connected name" },
  805. { 0x92, "Originating restrictions" },
  806. { 0x93, "Date & time of day" },
  807. { 0x94, "Call Appearance ID" },
  808. { 0x95, "Feature address" },
  809. { 0x96, "Redirection name" },
  810. { 0x9e, "Text" },
  811. };
  812. #define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag)
  813. static int
  814. disptext_ni1(char *dest, u_char * p)
  815. {
  816. char *dp = dest;
  817. int l, tag, len, i;
  818. p++;
  819. l = *p++ - 1;
  820. if (*p++ != 0x80) {
  821. dp += sprintf(dp, "    Unknown display typen");
  822. return (dp - dest);
  823. }
  824. /* Iterate over all tag,length,text fields */
  825. while (l > 0) {
  826. tag = *p++;
  827. len = *p++;
  828. l -= len + 2;
  829. /* Don't space or skip */
  830. if ((tag == 0x80) || (tag == 0x81)) p++;
  831. else {
  832. for (i = 0; i < DTAGSIZE; i++)
  833. if (tag == dtaglist[i].nr)
  834. break;
  835. /* When not found, give appropriate msg */
  836. if (i != DTAGSIZE) {
  837. dp += sprintf(dp, "    %s: ", dtaglist[i].descr);
  838. while (len--)
  839. *dp++ = *p++;
  840. } else {
  841. dp += sprintf(dp, "    (unknown display tag %2x): ", tag);
  842. while (len--)
  843. *dp++ = *p++;
  844. }
  845. dp += sprintf(dp, "n");
  846.                 }
  847. }
  848. return (dp - dest);
  849. }
  850. static int
  851. display(char *dest, u_char * p)
  852. {
  853. char *dp = dest;
  854. char ch = ' ';
  855. int l, octet = 3;
  856. p++;
  857. l = *p++;
  858. /* Iterate over all octets in the * display-information element */
  859. dp += sprintf(dp, "   "");
  860. while (l--) {
  861. dp += sprintf(dp, "%c", *p++);
  862. /* last octet in group? */
  863. if (*p & 0x80) {
  864. octet++;
  865. ch = ' ';
  866. } else if (ch == ' ')
  867. ch = 'a';
  868. else
  869. ch++;
  870. }
  871. *dp++ = '"';
  872. *dp++ = 'n';
  873. return (dp - dest);
  874. }
  875. int
  876. prfacility(char *dest, u_char * p)
  877. {
  878. char *dp = dest;
  879. int l, l2;
  880. p++;
  881. l = *p++;
  882. dp += sprintf(dp, "    octet 3 ");
  883. dp += prbits(dp, *p++, 8, 8);
  884. dp += sprintf(dp, "n");
  885. l -= 1;
  886. while (l > 0) {
  887. dp += sprintf(dp, "   octet 4 ");
  888. dp += prbits(dp, *p++, 8, 8);
  889. dp += sprintf(dp, "n");
  890. dp += sprintf(dp, "   octet 5 %dn", l2 = *p++ & 0x7f);
  891. l -= 2;
  892. dp += sprintf(dp, "   contents ");
  893. while (l2--) {
  894. dp += sprintf(dp, "%2x ", *p++);
  895. l--;
  896. }
  897. dp += sprintf(dp, "n");
  898. }
  899. return (dp - dest);
  900. }
  901. static
  902. struct InformationElement {
  903. u_char nr;
  904. char *descr;
  905. int (*f) (char *, u_char *);
  906. } ielist[] = {
  907. {
  908. 0x00, "Segmented message", general
  909. },
  910. {
  911. 0x04, "Bearer capability", prbearer
  912. },
  913. {
  914. 0x08, "Cause", prcause
  915. },
  916. {
  917. 0x10, "Call identity", general
  918. },
  919. {
  920. 0x14, "Call state", general
  921. },
  922. {
  923. 0x18, "Channel identification", prchident
  924. },
  925. {
  926. 0x1c, "Facility", prfacility
  927. },
  928. {
  929. 0x1e, "Progress indicator", general
  930. },
  931. {
  932. 0x20, "Network-specific facilities", general
  933. },
  934. {
  935. 0x27, "Notification indicator", general
  936. },
  937. {
  938. 0x28, "Display", display
  939. },
  940. {
  941. 0x29, "Date/Time", general
  942. },
  943. {
  944. 0x2c, "Keypad facility", general
  945. },
  946. {
  947. 0x34, "Signal", general
  948. },
  949. {
  950. 0x40, "Information rate", general
  951. },
  952. {
  953. 0x42, "End-to-end delay", general
  954. },
  955. {
  956. 0x43, "Transit delay selection and indication", general
  957. },
  958. {
  959. 0x44, "Packet layer binary parameters", general
  960. },
  961. {
  962. 0x45, "Packet layer window size", general
  963. },
  964. {
  965. 0x46, "Packet size", general
  966. },
  967. {
  968. 0x47, "Closed user group", general
  969. },
  970. {
  971. 0x4a, "Reverse charge indication", general
  972. },
  973. {
  974. 0x6c, "Calling party number", prcalling
  975. },
  976. {
  977. 0x6d, "Calling party subaddress", general
  978. },
  979. {
  980. 0x70, "Called party number", prcalled
  981. },
  982. {
  983. 0x71, "Called party subaddress", general
  984. },
  985. {
  986. 0x74, "Redirecting number", general
  987. },
  988. {
  989. 0x78, "Transit network selection", general
  990. },
  991. {
  992. 0x79, "Restart indicator", general
  993. },
  994. {
  995. 0x7c, "Low layer compatibility", general
  996. },
  997. {
  998. 0x7d, "High layer compatibility", general
  999. },
  1000. {
  1001. 0x7e, "User-user", general
  1002. },
  1003. {
  1004. 0x7f, "Escape for extension", general
  1005. },
  1006. };
  1007. #define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
  1008. static
  1009. struct InformationElement ielist_ni1[] = {
  1010. { 0x04, "Bearer Capability", prbearer_ni1 },
  1011. { 0x08, "Cause", prcause },
  1012. { 0x14, "Call State", general_ni1 },
  1013. { 0x18, "Channel Identification", prchident },
  1014. { 0x1e, "Progress Indicator", general_ni1 },
  1015. { 0x27, "Notification Indicator", general_ni1 },
  1016. { 0x2c, "Keypad Facility", prtext },
  1017. { 0x32, "Information Request", general_ni1 },
  1018. { 0x34, "Signal", general_ni1 },
  1019. { 0x38, "Feature Activation", general_ni1 },
  1020. { 0x39, "Feature Indication", prfeatureind },
  1021. { 0x3a, "Service Profile Identification (SPID)", prtext },
  1022. { 0x3b, "Endpoint Identifier", general_ni1 },
  1023. { 0x6c, "Calling Party Number", prcalling },
  1024. { 0x6d, "Calling Party Subaddress", general_ni1 },
  1025. { 0x70, "Called Party Number", prcalled },
  1026. { 0x71, "Called Party Subaddress", general_ni1 },
  1027. { 0x74, "Redirecting Number", general_ni1 },
  1028. { 0x78, "Transit Network Selection", general_ni1 },
  1029. { 0x7c, "Low Layer Compatibility", general_ni1 },
  1030. { 0x7d, "High Layer Compatibility", general_ni1 },
  1031. };
  1032. #define IESIZE_NI1 sizeof(ielist_ni1)/sizeof(struct InformationElement)
  1033. static
  1034. struct InformationElement ielist_ni1_cs5[] = {
  1035. { 0x1d, "Operator system access", general_ni1 },
  1036. { 0x2a, "Display text", disptext_ni1 },
  1037. };
  1038. #define IESIZE_NI1_CS5 sizeof(ielist_ni1_cs5)/sizeof(struct InformationElement)
  1039. static
  1040. struct InformationElement ielist_ni1_cs6[] = {
  1041. { 0x7b, "Call appearance", general_ni1 },
  1042. };
  1043. #define IESIZE_NI1_CS6 sizeof(ielist_ni1_cs6)/sizeof(struct InformationElement)
  1044. static struct InformationElement we_0[] =
  1045. {
  1046. {WE0_cause, "Cause", prcause_1tr6},
  1047. {WE0_connAddr, "Connecting Address", prcalled},
  1048. {WE0_callID, "Call IDentity", general},
  1049. {WE0_chanID, "Channel IDentity", general},
  1050. {WE0_netSpecFac, "Network Specific Facility", general},
  1051. {WE0_display, "Display", general},
  1052. {WE0_keypad, "Keypad", general},
  1053. {WE0_origAddr, "Origination Address", prcalled},
  1054. {WE0_destAddr, "Destination Address", prcalled},
  1055. {WE0_userInfo, "User Info", general}
  1056. };
  1057. #define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
  1058. static struct InformationElement we_6[] =
  1059. {
  1060. {WE6_serviceInd, "Service Indicator", general},
  1061. {WE6_chargingInfo, "Charging Information", prcharge},
  1062. {WE6_date, "Date", prtext},
  1063. {WE6_facSelect, "Facility Select", general},
  1064. {WE6_facStatus, "Facility Status", general},
  1065. {WE6_statusCalled, "Status Called", general},
  1066. {WE6_addTransAttr, "Additional Transmission Attributes", general}
  1067. };
  1068. #define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
  1069. int
  1070. QuickHex(char *txt, u_char * p, int cnt)
  1071. {
  1072. register int i;
  1073. register char *t = txt;
  1074. register u_char w;
  1075. for (i = 0; i < cnt; i++) {
  1076. *t++ = ' ';
  1077. w = (p[i] >> 4) & 0x0f;
  1078. if (w < 10)
  1079. *t++ = '0' + w;
  1080. else
  1081. *t++ = 'A' - 10 + w;
  1082. w = p[i] & 0x0f;
  1083. if (w < 10)
  1084. *t++ = '0' + w;
  1085. else
  1086. *t++ = 'A' - 10 + w;
  1087. }
  1088. *t++ = 0;
  1089. return (t - txt);
  1090. }
  1091. void
  1092. LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
  1093. {
  1094. char *dp;
  1095. if (size < 1)
  1096. return;
  1097. dp = cs->dlog;
  1098. if (size < MAX_DLOG_SPACE / 3 - 10) {
  1099. *dp++ = 'H';
  1100. *dp++ = 'E';
  1101. *dp++ = 'X';
  1102. *dp++ = ':';
  1103. dp += QuickHex(dp, buf, size);
  1104. dp--;
  1105. *dp++ = 'n';
  1106. *dp = 0;
  1107. HiSax_putstatus(cs, NULL, cs->dlog);
  1108. } else
  1109. HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
  1110. }
  1111. void
  1112. dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
  1113. {
  1114. u_char *bend, *buf;
  1115. char *dp;
  1116. unsigned char pd, cr_l, cr, mt;
  1117. unsigned char sapi, tei, ftyp;
  1118. int i, cset = 0, cs_old = 0, cs_fest = 0;
  1119. int size, finish = 0;
  1120. if (skb->len < 3)
  1121. return;
  1122. /* display header */
  1123. dp = cs->dlog;
  1124. dp += jiftime(dp, jiffies);
  1125. *dp++ = ' ';
  1126. sapi = skb->data[0] >> 2;
  1127. tei  = skb->data[1] >> 1;
  1128. ftyp = skb->data[2];
  1129. buf = skb->data;
  1130. dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
  1131. size = skb->len;
  1132. if (tei == GROUP_TEI) {
  1133. if (sapi == CTRL_SAPI) { /* sapi 0 */
  1134. if (ftyp == 3) {
  1135. dp += sprintf(dp, "broadcastn");
  1136. buf += 3;
  1137. size -= 3;
  1138. } else {
  1139. dp += sprintf(dp, "no UI broadcastn");
  1140. finish = 1;
  1141. }
  1142. } else if (sapi == TEI_SAPI) {
  1143. dp += sprintf(dp, "tei managementn");
  1144. finish = 1;
  1145. } else {
  1146. dp += sprintf(dp, "unknown sapi %d broadcastn", sapi);
  1147. finish = 1;
  1148. }
  1149. } else {
  1150. if (sapi == CTRL_SAPI) {
  1151. if (!(ftyp & 1)) { /* IFrame */
  1152. dp += sprintf(dp, "with tei %dn", tei);
  1153. buf += 4;
  1154. size -= 4;
  1155. } else {
  1156. dp += sprintf(dp, "SFrame with tei %dn", tei);
  1157. finish = 1;
  1158. }
  1159. } else {
  1160. dp += sprintf(dp, "unknown sapi %d tei %dn", sapi, tei);
  1161. finish = 1;
  1162. }
  1163. }
  1164. bend = skb->data + skb->len;
  1165. if (buf >= bend) {
  1166. dp += sprintf(dp, "frame too shortn");
  1167. finish = 1;
  1168. }
  1169. if (finish) {
  1170. *dp = 0;
  1171. HiSax_putstatus(cs, NULL, cs->dlog);
  1172. return;
  1173. }
  1174. if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */
  1175. /* locate message type */
  1176. pd = *buf++;
  1177. cr_l = *buf++;
  1178. if (cr_l)
  1179. cr = *buf++;
  1180. else
  1181. cr = 0;
  1182. mt = *buf++;
  1183. if (pd == PROTO_DIS_N0) { /* N0 */
  1184. for (i = 0; i < MT_N0_LEN; i++)
  1185. if (mt_n0[i].nr == mt)
  1186. break;
  1187. /* display message type if it exists */
  1188. if (i == MT_N0_LEN)
  1189. dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!n",
  1190.       cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1191.       size, mt);
  1192. else
  1193. dp += sprintf(dp, "callref %d %s size %d message type %sn",
  1194.       cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1195.       size, mt_n0[i].descr);
  1196. } else { /* N1 */
  1197. for (i = 0; i < MT_N1_LEN; i++)
  1198. if (mt_n1[i].nr == mt)
  1199. break;
  1200. /* display message type if it exists */
  1201. if (i == MT_N1_LEN)
  1202. dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!n",
  1203.       cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1204.       size, mt);
  1205. else
  1206. dp += sprintf(dp, "callref %d %s size %d message type %sn",
  1207.       cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1208.       size, mt_n1[i].descr);
  1209. }
  1210. /* display each information element */
  1211. while (buf < bend) {
  1212. /* Is it a single octet information element? */
  1213. if (*buf & 0x80) {
  1214. switch ((*buf >> 4) & 7) {
  1215. case 1:
  1216. dp += sprintf(dp, "  Shift %xn", *buf & 0xf);
  1217. cs_old = cset;
  1218. cset = *buf & 7;
  1219. cs_fest = *buf & 8;
  1220. break;
  1221. case 3:
  1222. dp += sprintf(dp, "  Congestion level %xn", *buf & 0xf);
  1223. break;
  1224. case 2:
  1225. if (*buf == 0xa0) {
  1226. dp += sprintf(dp, "  More datan");
  1227. break;
  1228. }
  1229. if (*buf == 0xa1) {
  1230. dp += sprintf(dp, "  Sending completen");
  1231. }
  1232. break;
  1233. /* fall through */
  1234. default:
  1235. dp += sprintf(dp, "  Reserved %xn", *buf);
  1236. break;
  1237. }
  1238. buf++;
  1239. continue;
  1240. }
  1241. /* No, locate it in the table */
  1242. if (cset == 0) {
  1243. for (i = 0; i < WE_0_LEN; i++)
  1244. if (*buf == we_0[i].nr)
  1245. break;
  1246. /* When found, give appropriate msg */
  1247. if (i != WE_0_LEN) {
  1248. dp += sprintf(dp, "  %sn", we_0[i].descr);
  1249. dp += we_0[i].f(dp, buf);
  1250. } else
  1251. dp += sprintf(dp, "  Codeset %d attribute %x attribute size %dn", cset, *buf, buf[1]);
  1252. } else if (cset == 6) {
  1253. for (i = 0; i < WE_6_LEN; i++)
  1254. if (*buf == we_6[i].nr)
  1255. break;
  1256. /* When found, give appropriate msg */
  1257. if (i != WE_6_LEN) {
  1258. dp += sprintf(dp, "  %sn", we_6[i].descr);
  1259. dp += we_6[i].f(dp, buf);
  1260. } else
  1261. dp += sprintf(dp, "  Codeset %d attribute %x attribute size %dn", cset, *buf, buf[1]);
  1262. } else
  1263. dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %dn", cset, *buf, buf[1]);
  1264. /* Skip to next element */
  1265. if (cs_fest == 8) {
  1266. cset = cs_old;
  1267. cs_old = 0;
  1268. cs_fest = 0;
  1269. }
  1270. buf += buf[1] + 2;
  1271. }
  1272. } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_NI1)) { /* NI-1 */
  1273. /* locate message type */
  1274. buf++;
  1275. cr_l = *buf++;
  1276. if (cr_l)
  1277. cr = *buf++;
  1278. else
  1279. cr = 0;
  1280. mt = *buf++;
  1281. for (i = 0; i < MTSIZE; i++)
  1282. if (mtlist[i].nr == mt)
  1283. break;
  1284. /* display message type if it exists */
  1285. if (i == MTSIZE)
  1286. dp += sprintf(dp, "callref %d %s size %d unknown message type %x!n",
  1287.     cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1288.       size, mt);
  1289. else
  1290. dp += sprintf(dp, "callref %d %s size %d message type %sn",
  1291.     cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1292.       size, mtlist[i].descr);
  1293. /* display each information element */
  1294. while (buf < bend) {
  1295. /* Is it a single octet information element? */
  1296. if (*buf & 0x80) {
  1297. switch ((*buf >> 4) & 7) {
  1298. case 1:
  1299. dp += sprintf(dp, "  Shift %xn", *buf & 0xf);
  1300. cs_old = cset;
  1301. cset = *buf & 7;
  1302. cs_fest = *buf & 8;
  1303. break;
  1304. default:
  1305. dp += sprintf(dp, "  Unknown single-octet IE %xn", *buf);
  1306. break;
  1307. }
  1308. buf++;
  1309. continue;
  1310. }
  1311. /* No, locate it in the table */
  1312. if (cset == 0) {
  1313. for (i = 0; i < IESIZE; i++)
  1314. if (*buf == ielist_ni1[i].nr)
  1315. break;
  1316. /* When not found, give appropriate msg */
  1317. if (i != IESIZE) {
  1318. dp += sprintf(dp, "  %sn", ielist_ni1[i].descr);
  1319. dp += ielist_ni1[i].f(dp, buf);
  1320. } else
  1321. dp += sprintf(dp, "  attribute %x attribute size %dn", *buf, buf[1]);
  1322. } else if (cset == 5) {
  1323. for (i = 0; i < IESIZE_NI1_CS5; i++)
  1324. if (*buf == ielist_ni1_cs5[i].nr)
  1325. break;
  1326. /* When not found, give appropriate msg */
  1327. if (i != IESIZE_NI1_CS5) {
  1328. dp += sprintf(dp, "  %sn", ielist_ni1_cs5[i].descr);
  1329. dp += ielist_ni1_cs5[i].f(dp, buf);
  1330. } else
  1331. dp += sprintf(dp, "  attribute %x attribute size %dn", *buf, buf[1]);
  1332. } else if (cset == 6) {
  1333. for (i = 0; i < IESIZE_NI1_CS6; i++)
  1334. if (*buf == ielist_ni1_cs6[i].nr)
  1335. break;
  1336. /* When not found, give appropriate msg */
  1337. if (i != IESIZE_NI1_CS6) {
  1338. dp += sprintf(dp, "  %sn", ielist_ni1_cs6[i].descr);
  1339. dp += ielist_ni1_cs6[i].f(dp, buf);
  1340. } else
  1341. dp += sprintf(dp, "  attribute %x attribute size %dn", *buf, buf[1]);
  1342. } else
  1343. dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %dn", cset, *buf, buf[1]);
  1344. /* Skip to next element */
  1345. if (cs_fest == 8) {
  1346. cset = cs_old;
  1347. cs_old = 0;
  1348. cs_fest = 0;
  1349. }
  1350. buf += buf[1] + 2;
  1351. }
  1352. } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_EURO)) { /* EURO */
  1353. /* locate message type */
  1354. buf++;
  1355. cr_l = *buf++;
  1356. if (cr_l)
  1357. cr = *buf++;
  1358. else
  1359. cr = 0;
  1360. mt = *buf++;
  1361. for (i = 0; i < MTSIZE; i++)
  1362. if (mtlist[i].nr == mt)
  1363. break;
  1364. /* display message type if it exists */
  1365. if (i == MTSIZE)
  1366. dp += sprintf(dp, "callref %d %s size %d unknown message type %x!n",
  1367.     cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1368.       size, mt);
  1369. else
  1370. dp += sprintf(dp, "callref %d %s size %d message type %sn",
  1371.     cr & 0x7f, (cr & 0x80) ? "called" : "caller",
  1372.       size, mtlist[i].descr);
  1373. /* display each information element */
  1374. while (buf < bend) {
  1375. /* Is it a single octet information element? */
  1376. if (*buf & 0x80) {
  1377. switch ((*buf >> 4) & 7) {
  1378. case 1:
  1379. dp += sprintf(dp, "  Shift %xn", *buf & 0xf);
  1380. break;
  1381. case 3:
  1382. dp += sprintf(dp, "  Congestion level %xn", *buf & 0xf);
  1383. break;
  1384. case 5:
  1385. dp += sprintf(dp, "  Repeat indicator %xn", *buf & 0xf);
  1386. break;
  1387. case 2:
  1388. if (*buf == 0xa0) {
  1389. dp += sprintf(dp, "  More datan");
  1390. break;
  1391. }
  1392. if (*buf == 0xa1) {
  1393. dp += sprintf(dp, "  Sending completen");
  1394. }
  1395. break;
  1396. /* fall through */
  1397. default:
  1398. dp += sprintf(dp, "  Reserved %xn", *buf);
  1399. break;
  1400. }
  1401. buf++;
  1402. continue;
  1403. }
  1404. /* No, locate it in the table */
  1405. for (i = 0; i < IESIZE; i++)
  1406. if (*buf == ielist[i].nr)
  1407. break;
  1408. /* When not found, give appropriate msg */
  1409. if (i != IESIZE) {
  1410. dp += sprintf(dp, "  %sn", ielist[i].descr);
  1411. dp += ielist[i].f(dp, buf);
  1412. } else
  1413. dp += sprintf(dp, "  attribute %x attribute size %dn", *buf, buf[1]);
  1414. /* Skip to next element */
  1415. buf += buf[1] + 2;
  1416. }
  1417. } else {
  1418. dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
  1419. }
  1420. *dp = 0;
  1421. HiSax_putstatus(cs, NULL, cs->dlog);
  1422. }