diff options
Diffstat (limited to 'drivers/isdn/capi/capiutil.c')
-rw-r--r-- | drivers/isdn/capi/capiutil.c | 254 |
1 files changed, 208 insertions, 46 deletions
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index c1b21552fc03..ad1e2702c2d1 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c | |||
@@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd) | |||
648 | 648 | ||
649 | 649 | ||
650 | /*-------------------------------------------------------*/ | 650 | /*-------------------------------------------------------*/ |
651 | |||
652 | #ifdef CONFIG_CAPI_TRACE | ||
653 | |||
651 | /*-------------------------------------------------------*/ | 654 | /*-------------------------------------------------------*/ |
652 | 655 | ||
653 | static char *pnames[] = | 656 | static char *pnames[] = |
@@ -703,44 +706,77 @@ static char *pnames[] = | |||
703 | }; | 706 | }; |
704 | 707 | ||
705 | 708 | ||
706 | static char buf[8192]; | ||
707 | static char *p = NULL; | ||
708 | 709 | ||
709 | #include <stdarg.h> | 710 | #include <stdarg.h> |
710 | 711 | ||
711 | /*-------------------------------------------------------*/ | 712 | /*-------------------------------------------------------*/ |
712 | static void bufprint(char *fmt,...) | 713 | static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...) |
713 | { | 714 | { |
714 | va_list f; | 715 | va_list f; |
716 | size_t n,r; | ||
717 | |||
718 | if (!cdb) | ||
719 | return NULL; | ||
715 | va_start(f, fmt); | 720 | va_start(f, fmt); |
716 | vsprintf(p, fmt, f); | 721 | r = cdb->size - cdb->pos; |
722 | n = vsnprintf(cdb->p, r, fmt, f); | ||
717 | va_end(f); | 723 | va_end(f); |
718 | p += strlen(p); | 724 | if (n >= r) { |
725 | /* truncated, need bigger buffer */ | ||
726 | size_t ns = 2 * cdb->size; | ||
727 | u_char *nb; | ||
728 | |||
729 | while ((ns - cdb->pos) <= n) | ||
730 | ns *= 2; | ||
731 | nb = kmalloc(ns, GFP_ATOMIC); | ||
732 | if (!nb) { | ||
733 | cdebbuf_free(cdb); | ||
734 | return NULL; | ||
735 | } | ||
736 | memcpy(nb, cdb->buf, cdb->pos); | ||
737 | kfree(cdb->buf); | ||
738 | nb[cdb->pos] = 0; | ||
739 | cdb->buf = nb; | ||
740 | cdb->p = cdb->buf + cdb->pos; | ||
741 | cdb->size = ns; | ||
742 | va_start(f, fmt); | ||
743 | r = cdb->size - cdb->pos; | ||
744 | n = vsnprintf(cdb->p, r, fmt, f); | ||
745 | va_end(f); | ||
746 | } | ||
747 | cdb->p += n; | ||
748 | cdb->pos += n; | ||
749 | return cdb; | ||
719 | } | 750 | } |
720 | 751 | ||
721 | static void printstructlen(u8 * m, unsigned len) | 752 | static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len) |
722 | { | 753 | { |
723 | unsigned hex = 0; | 754 | unsigned hex = 0; |
755 | |||
756 | if (!cdb) | ||
757 | return NULL; | ||
724 | for (; len; len--, m++) | 758 | for (; len; len--, m++) |
725 | if (isalnum(*m) || *m == ' ') { | 759 | if (isalnum(*m) || *m == ' ') { |
726 | if (hex) | 760 | if (hex) |
727 | bufprint(">"); | 761 | cdb = bufprint(cdb, ">"); |
728 | bufprint("%c", *m); | 762 | cdb = bufprint(cdb, "%c", *m); |
729 | hex = 0; | 763 | hex = 0; |
730 | } else { | 764 | } else { |
731 | if (!hex) | 765 | if (!hex) |
732 | bufprint("<%02x", *m); | 766 | cdb = bufprint(cdb, "<%02x", *m); |
733 | else | 767 | else |
734 | bufprint(" %02x", *m); | 768 | cdb = bufprint(cdb, " %02x", *m); |
735 | hex = 1; | 769 | hex = 1; |
736 | } | 770 | } |
737 | if (hex) | 771 | if (hex) |
738 | bufprint(">"); | 772 | cdb = bufprint(cdb, ">"); |
773 | return cdb; | ||
739 | } | 774 | } |
740 | 775 | ||
741 | static void printstruct(u8 * m) | 776 | static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m) |
742 | { | 777 | { |
743 | unsigned len; | 778 | unsigned len; |
779 | |||
744 | if (m[0] != 0xff) { | 780 | if (m[0] != 0xff) { |
745 | len = m[0]; | 781 | len = m[0]; |
746 | m += 1; | 782 | m += 1; |
@@ -748,42 +784,45 @@ static void printstruct(u8 * m) | |||
748 | len = ((u16 *) (m + 1))[0]; | 784 | len = ((u16 *) (m + 1))[0]; |
749 | m += 3; | 785 | m += 3; |
750 | } | 786 | } |
751 | printstructlen(m, len); | 787 | cdb = printstructlen(cdb, m, len); |
788 | return cdb; | ||
752 | } | 789 | } |
753 | 790 | ||
754 | /*-------------------------------------------------------*/ | 791 | /*-------------------------------------------------------*/ |
755 | #define NAME (pnames[cmsg->par[cmsg->p]]) | 792 | #define NAME (pnames[cmsg->par[cmsg->p]]) |
756 | 793 | ||
757 | static void protocol_message_2_pars(_cmsg * cmsg, int level) | 794 | static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level) |
758 | { | 795 | { |
759 | for (; TYP != _CEND; cmsg->p++) { | 796 | for (; TYP != _CEND; cmsg->p++) { |
760 | int slen = 29 + 3 - level; | 797 | int slen = 29 + 3 - level; |
761 | int i; | 798 | int i; |
762 | 799 | ||
763 | bufprint(" "); | 800 | if (!cdb) |
801 | return NULL; | ||
802 | cdb = bufprint(cdb, " "); | ||
764 | for (i = 0; i < level - 1; i++) | 803 | for (i = 0; i < level - 1; i++) |
765 | bufprint(" "); | 804 | cdb = bufprint(cdb, " "); |
766 | 805 | ||
767 | switch (TYP) { | 806 | switch (TYP) { |
768 | case _CBYTE: | 807 | case _CBYTE: |
769 | bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); | 808 | cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); |
770 | cmsg->l++; | 809 | cmsg->l++; |
771 | break; | 810 | break; |
772 | case _CWORD: | 811 | case _CWORD: |
773 | bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); | 812 | cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); |
774 | cmsg->l += 2; | 813 | cmsg->l += 2; |
775 | break; | 814 | break; |
776 | case _CDWORD: | 815 | case _CDWORD: |
777 | bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); | 816 | cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); |
778 | cmsg->l += 4; | 817 | cmsg->l += 4; |
779 | break; | 818 | break; |
780 | case _CSTRUCT: | 819 | case _CSTRUCT: |
781 | bufprint("%-*s = ", slen, NAME); | 820 | cdb = bufprint(cdb, "%-*s = ", slen, NAME); |
782 | if (cmsg->m[cmsg->l] == '\0') | 821 | if (cmsg->m[cmsg->l] == '\0') |
783 | bufprint("default"); | 822 | cdb = bufprint(cdb, "default"); |
784 | else | 823 | else |
785 | printstruct(cmsg->m + cmsg->l); | 824 | cdb = printstruct(cdb, cmsg->m + cmsg->l); |
786 | bufprint("\n"); | 825 | cdb = bufprint(cdb, "\n"); |
787 | if (cmsg->m[cmsg->l] != 0xff) | 826 | if (cmsg->m[cmsg->l] != 0xff) |
788 | cmsg->l += 1 + cmsg->m[cmsg->l]; | 827 | cmsg->l += 1 + cmsg->m[cmsg->l]; |
789 | else | 828 | else |
@@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level) | |||
794 | case _CMSTRUCT: | 833 | case _CMSTRUCT: |
795 | /*----- Metastruktur 0 -----*/ | 834 | /*----- Metastruktur 0 -----*/ |
796 | if (cmsg->m[cmsg->l] == '\0') { | 835 | if (cmsg->m[cmsg->l] == '\0') { |
797 | bufprint("%-*s = default\n", slen, NAME); | 836 | cdb = bufprint(cdb, "%-*s = default\n", slen, NAME); |
798 | cmsg->l++; | 837 | cmsg->l++; |
799 | jumpcstruct(cmsg); | 838 | jumpcstruct(cmsg); |
800 | } else { | 839 | } else { |
801 | char *name = NAME; | 840 | char *name = NAME; |
802 | unsigned _l = cmsg->l; | 841 | unsigned _l = cmsg->l; |
803 | bufprint("%-*s\n", slen, name); | 842 | cdb = bufprint(cdb, "%-*s\n", slen, name); |
804 | cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; | 843 | cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; |
805 | cmsg->p++; | 844 | cmsg->p++; |
806 | protocol_message_2_pars(cmsg, level + 1); | 845 | cdb = protocol_message_2_pars(cdb, cmsg, level + 1); |
807 | } | 846 | } |
808 | break; | 847 | break; |
809 | } | 848 | } |
810 | } | 849 | } |
850 | return cdb; | ||
811 | } | 851 | } |
812 | /*-------------------------------------------------------*/ | 852 | /*-------------------------------------------------------*/ |
813 | char *capi_message2str(u8 * msg) | 853 | |
854 | static _cdebbuf *g_debbuf; | ||
855 | static u_long g_debbuf_lock; | ||
856 | static _cmsg *g_cmsg; | ||
857 | |||
858 | _cdebbuf *cdebbuf_alloc(void) | ||
814 | { | 859 | { |
860 | _cdebbuf *cdb; | ||
861 | |||
862 | if (likely(!test_and_set_bit(1, &g_debbuf_lock))) { | ||
863 | cdb = g_debbuf; | ||
864 | goto init; | ||
865 | } else | ||
866 | cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC); | ||
867 | if (!cdb) | ||
868 | return NULL; | ||
869 | cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC); | ||
870 | if (!cdb->buf) { | ||
871 | kfree(cdb); | ||
872 | return NULL; | ||
873 | } | ||
874 | cdb->size = CDEBUG_SIZE; | ||
875 | init: | ||
876 | cdb->buf[0] = 0; | ||
877 | cdb->p = cdb->buf; | ||
878 | cdb->pos = 0; | ||
879 | return cdb; | ||
880 | } | ||
815 | 881 | ||
816 | _cmsg cmsg; | 882 | void cdebbuf_free(_cdebbuf *cdb) |
817 | p = buf; | 883 | { |
818 | p[0] = 0; | 884 | if (likely(cdb == g_debbuf)) { |
885 | test_and_clear_bit(1, &g_debbuf_lock); | ||
886 | return; | ||
887 | } | ||
888 | if (likely(cdb)) | ||
889 | kfree(cdb->buf); | ||
890 | kfree(cdb); | ||
891 | } | ||
819 | 892 | ||
820 | cmsg.m = msg; | ||
821 | cmsg.l = 8; | ||
822 | cmsg.p = 0; | ||
823 | byteTRcpy(cmsg.m + 4, &cmsg.Command); | ||
824 | byteTRcpy(cmsg.m + 5, &cmsg.Subcommand); | ||
825 | cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)]; | ||
826 | 893 | ||
827 | bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", | 894 | _cdebbuf *capi_message2str(u8 * msg) |
828 | mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], | 895 | { |
896 | _cdebbuf *cdb; | ||
897 | _cmsg *cmsg; | ||
898 | |||
899 | cdb = cdebbuf_alloc(); | ||
900 | if (unlikely(!cdb)) | ||
901 | return NULL; | ||
902 | if (likely(cdb == g_debbuf)) | ||
903 | cmsg = g_cmsg; | ||
904 | else | ||
905 | cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC); | ||
906 | if (unlikely(!cmsg)) { | ||
907 | cdebbuf_free(cdb); | ||
908 | return NULL; | ||
909 | } | ||
910 | cmsg->m = msg; | ||
911 | cmsg->l = 8; | ||
912 | cmsg->p = 0; | ||
913 | byteTRcpy(cmsg->m + 4, &cmsg->Command); | ||
914 | byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); | ||
915 | cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; | ||
916 | |||
917 | cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n", | ||
918 | mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], | ||
829 | ((unsigned short *) msg)[1], | 919 | ((unsigned short *) msg)[1], |
830 | ((unsigned short *) msg)[3], | 920 | ((unsigned short *) msg)[3], |
831 | ((unsigned short *) msg)[0]); | 921 | ((unsigned short *) msg)[0]); |
832 | 922 | ||
833 | protocol_message_2_pars(&cmsg, 1); | 923 | cdb = protocol_message_2_pars(cdb, cmsg, 1); |
834 | return buf; | 924 | if (unlikely(cmsg != g_cmsg)) |
925 | kfree(cmsg); | ||
926 | return cdb; | ||
835 | } | 927 | } |
836 | 928 | ||
837 | char *capi_cmsg2str(_cmsg * cmsg) | 929 | _cdebbuf *capi_cmsg2str(_cmsg * cmsg) |
838 | { | 930 | { |
839 | p = buf; | 931 | _cdebbuf *cdb; |
840 | p[0] = 0; | 932 | |
933 | cdb = cdebbuf_alloc(); | ||
934 | if (!cdb) | ||
935 | return NULL; | ||
841 | cmsg->l = 8; | 936 | cmsg->l = 8; |
842 | cmsg->p = 0; | 937 | cmsg->p = 0; |
843 | bufprint("%s ID=%03d #0x%04x LEN=%04d\n", | 938 | cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", |
844 | mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], | 939 | mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], |
845 | ((u16 *) cmsg->m)[1], | 940 | ((u16 *) cmsg->m)[1], |
846 | ((u16 *) cmsg->m)[3], | 941 | ((u16 *) cmsg->m)[3], |
847 | ((u16 *) cmsg->m)[0]); | 942 | ((u16 *) cmsg->m)[0]); |
848 | protocol_message_2_pars(cmsg, 1); | 943 | cdb = protocol_message_2_pars(cdb, cmsg, 1); |
849 | return buf; | 944 | return cdb; |
850 | } | 945 | } |
851 | 946 | ||
947 | int __init cdebug_init(void) | ||
948 | { | ||
949 | g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL); | ||
950 | if (!g_cmsg) | ||
951 | return ENOMEM; | ||
952 | g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL); | ||
953 | if (!g_debbuf) { | ||
954 | kfree(g_cmsg); | ||
955 | return ENOMEM; | ||
956 | } | ||
957 | g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL); | ||
958 | if (!g_debbuf->buf) { | ||
959 | kfree(g_cmsg); | ||
960 | kfree(g_debbuf); | ||
961 | return ENOMEM;; | ||
962 | } | ||
963 | g_debbuf->size = CDEBUG_GSIZE; | ||
964 | g_debbuf->buf[0] = 0; | ||
965 | g_debbuf->p = g_debbuf->buf; | ||
966 | g_debbuf->pos = 0; | ||
967 | return 0; | ||
968 | } | ||
969 | |||
970 | void __exit cdebug_exit(void) | ||
971 | { | ||
972 | if (g_debbuf) | ||
973 | kfree(g_debbuf->buf); | ||
974 | kfree(g_debbuf); | ||
975 | kfree(g_cmsg); | ||
976 | } | ||
977 | |||
978 | #else /* !CONFIG_CAPI_TRACE */ | ||
979 | |||
980 | static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0}; | ||
981 | |||
982 | _cdebbuf *capi_message2str(u8 * msg) | ||
983 | { | ||
984 | return &g_debbuf; | ||
985 | } | ||
986 | |||
987 | _cdebbuf *capi_cmsg2str(_cmsg * cmsg) | ||
988 | { | ||
989 | return &g_debbuf; | ||
990 | } | ||
991 | |||
992 | _cdebbuf *cdebbuf_alloc(void) | ||
993 | { | ||
994 | return &g_debbuf; | ||
995 | } | ||
996 | |||
997 | void cdebbuf_free(_cdebbuf *cdb) | ||
998 | { | ||
999 | } | ||
1000 | |||
1001 | int __init cdebug_init(void) | ||
1002 | { | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | void __exit cdebug_exit(void) | ||
1007 | { | ||
1008 | } | ||
1009 | |||
1010 | #endif | ||
1011 | |||
1012 | EXPORT_SYMBOL(cdebbuf_alloc); | ||
1013 | EXPORT_SYMBOL(cdebbuf_free); | ||
852 | EXPORT_SYMBOL(capi_cmsg2message); | 1014 | EXPORT_SYMBOL(capi_cmsg2message); |
853 | EXPORT_SYMBOL(capi_message2cmsg); | 1015 | EXPORT_SYMBOL(capi_message2cmsg); |
854 | EXPORT_SYMBOL(capi_cmsg_header); | 1016 | EXPORT_SYMBOL(capi_cmsg_header); |