Compare commits
702 Commits
Author | SHA1 | Date |
---|---|---|
MelwareDE | c02af7806f | |
MelwareDE | 07f6d27017 | |
MelwareDE | 7de878e54d | |
MelwareDE | a054dff7ae | |
MelwareDE | c6946a40c8 | |
MelwareDE | ea23483041 | |
MelwareDE | 955b02d460 | |
MelwareDE | f143a92dd1 | |
MelwareDE | 840557751c | |
MelwareDE | 72111c4049 | |
MelwareDE | 20eef6a35a | |
MelwareDE | 850e8c24d1 | |
MelwareDE | 2ceebff2d9 | |
MelwareDE | 36c44f6e3f | |
MelwareDE | 0a308ee538 | |
MelwareDE | eb21edd1cf | |
MelwareDE | 37f2ff6580 | |
MelwareDE | 50df20964f | |
MelwareDE | 29b662a4b6 | |
MelwareDE | 02c9627241 | |
MelwareDE | 670b17998c | |
MelwareDE | 9fdc04e405 | |
MelwareDE | dcbb83ac1f | |
MelwareDE | 011b8e71f9 | |
MelwareDE | a195a39a55 | |
MelwareDE | 0f986eebc9 | |
MelwareDE | 6307669221 | |
MelwareDE | 49d3f54fcc | |
MelwareDE | 7cb0fe0e8f | |
MelwareDE | 00b4758564 | |
MelwareDE | c1e0bc653b | |
MelwareDE | 43e2232a0e | |
MelwareDE | 4411cbc18c | |
MelwareDE | f0c37c2067 | |
MelwareDE | c5a0982ee5 | |
MelwareDE | c4bc7f524b | |
MelwareDE | 78fd7fb7e5 | |
MelwareDE | 524cc0f1ac | |
MelwareDE | 21aa254147 | |
MelwareDE | 274a293f76 | |
MelwareDE | b684805ca1 | |
MelwareDE | 53915531f5 | |
MelwareDE | 578b7005c7 | |
MelwareDE | 08db9b6db3 | |
MelwareDE | 58cf952292 | |
MelwareDE | ca1b241cdf | |
MelwareDE | bad928afca | |
MelwareDE | 02d04c7e9d | |
MelwareDE | 22833e5ec7 | |
MelwareDE | c4a5d9e6d4 | |
MelwareDE | b75d1cbc3e | |
MelwareDE | 6decf34007 | |
MelwareDE | 3c491e7f65 | |
MelwareDE | 601e88e668 | |
MelwareDE | a952dcd336 | |
MelwareDE | 2a83825aaf | |
MelwareDE | ac9d6b319b | |
MelwareDE | 733395c63d | |
MelwareDE | 47a34d4bb9 | |
MelwareDE | c8baf15baa | |
MelwareDE | a60f4cf67a | |
MelwareDE | 29581c9637 | |
MelwareDE | e0484c4db5 | |
MelwareDE | 9f1b2b83cc | |
MelwareDE | 9a3483e6a0 | |
MelwareDE | 80b5145d6b | |
MelwareDE | 3b577b11ad | |
MelwareDE | ab7eff3897 | |
MelwareDE | 7bbeb7ecf6 | |
MelwareDE | 4f4b5bb6b6 | |
MelwareDE | e4de99914f | |
MelwareDE | d55a1dae94 | |
MelwareDE | 66562edbcc | |
MelwareDE | 420fdc352d | |
MelwareDE | 67b363c1c1 | |
MelwareDE | 487fb33bb9 | |
MelwareDE | 9c3cceccda | |
MelwareDE | d5c3b62610 | |
MelwareDE | 4ce2cebee5 | |
MelwareDE | 95d5034d2f | |
MelwareDE | 221d9ed595 | |
MelwareDE | 894853c92d | |
MelwareDE | bb674f18c1 | |
MelwareDE | 187d462cbd | |
MelwareDE | 6c7ba82edf | |
MelwareDE | 90557f5ced | |
MelwareDE | cd36dac329 | |
MelwareDE | 2db2bf01bd | |
MelwareDE | 17658c5edf | |
MelwareDE | fd7c663caf | |
MelwareDE | 7037ba337b | |
MelwareDE | 5940695186 | |
MelwareDE | e957372537 | |
MelwareDE | 10384d0bbf | |
MelwareDE | 8fb2018db7 | |
MelwareDE | e534562827 | |
MelwareDE | f7e19c4cad | |
MelwareDE | 341d1a2d31 | |
MelwareDE | b6811a3bc2 | |
MelwareDE | 01d9dbfa34 | |
MelwareDE | 5076ada4c7 | |
MelwareDE | 894406e419 | |
MelwareDE | 4219104f80 | |
MelwareDE | 14c3794527 | |
MelwareDE | 2c636c7484 | |
MelwareDE | e7da2a3aed | |
MelwareDE | 20d86c8a67 | |
MelwareDE | 8d916f3f90 | |
MelwareDE | cdd963d4cf | |
MelwareDE | 0128254592 | |
MelwareDE | 34cacdf2d3 | |
MelwareDE | eae8d38988 | |
MelwareDE | 2844c5b93a | |
MelwareDE | cba80e7f25 | |
MelwareDE | e26c9ed12a | |
MelwareDE | 5a5bedc999 | |
MelwareDE | 3e71cbcc24 | |
MelwareDE | f9f8279d8c | |
MelwareDE | 1d1fca7181 | |
MelwareDE | fc27be9222 | |
MelwareDE | 26f850ef44 | |
MelwareDE | 6611940b58 | |
MelwareDE | 83ba42f167 | |
MelwareDE | a98cfe0cc9 | |
MelwareDE | 9d669bc5c3 | |
MelwareDE | 5d0d05892b | |
MelwareDE | e590876769 | |
MelwareDE | a6f24499b8 | |
MelwareDE | fa4d1ef6ac | |
MelwareDE | 6fda685af2 | |
MelwareDE | 1eeb822d08 | |
MelwareDE | 06803fcc9f | |
MelwareDE | 999b9e306b | |
MelwareDE | 30d7131076 | |
MelwareDE | 3e891c11c1 | |
MelwareDE | 1782726ccd | |
MelwareDE | ae92425a79 | |
MelwareDE | 00d8e53e44 | |
MelwareDE | aad92617a7 | |
MelwareDE | fa901efa62 | |
MelwareDE | e3d9df8417 | |
MelwareDE | a4f7b18361 | |
MelwareDE | c5f9794303 | |
MelwareDE | 548a12ac9a | |
MelwareDE | 23307b78fb | |
MelwareDE | 0edff4c50d | |
MelwareDE | 32619ad1aa | |
MelwareDE | 10df6415d3 | |
MelwareDE | bb0fd3387f | |
MelwareDE | d492b5daa5 | |
MelwareDE | 412c182ee4 | |
MelwareDE | ed165f4a36 | |
MelwareDE | 0381db531a | |
MelwareDE | 2aeb53c779 | |
MelwareDE | dcfeb51b01 | |
MelwareDE | 7be7d7c6a9 | |
MelwareDE | bdedbef17e | |
MelwareDE | 7ebd347139 | |
MelwareDE | 27dc5e04a6 | |
MelwareDE | 5c9ae99157 | |
MelwareDE | 0c34043dfe | |
MelwareDE | 4f70be4d63 | |
MelwareDE | f129c0813d | |
MelwareDE | 6197ed537d | |
MelwareDE | 9fed7726d1 | |
MelwareDE | de67c79a12 | |
MelwareDE | 9d8d02961b | |
MelwareDE | 842012cc0f | |
MelwareDE | 57b9aa8bec | |
MelwareDE | dd6f38593c | |
MelwareDE | 77265e267b | |
MelwareDE | 3256ef3db9 | |
MelwareDE | 557768821c | |
MelwareDE | 325380b5e9 | |
MelwareDE | d6c8fe4db9 | |
MelwareDE | e8fdb10a41 | |
MelwareDE | 02e04fc7fd | |
MelwareDE | ce2dffd58d | |
MelwareDE | 890826688f | |
MelwareDE | d1e0d25194 | |
MelwareDE | 2fa97e73e7 | |
MelwareDE | ab01847bce | |
MelwareDE | 359049dfba | |
MelwareDE | 0904e9d00a | |
MelwareDE | ef1052e6af | |
MelwareDE | 2ed598ec08 | |
MelwareDE | d1d6574d68 | |
MelwareDE | a3c2bd09b2 | |
MelwareDE | aa71b0c410 | |
MelwareDE | 8eea241040 | |
MelwareDE | 5f588ddd6c | |
MelwareDE | 31db98fb9e | |
MelwareDE | bf1eb50548 | |
MelwareDE | d2094b25b7 | |
MelwareDE | b750187872 | |
MelwareDE | 4ffad9eebd | |
MelwareDE | a4b8a7db3a | |
MelwareDE | 244d5c0adc | |
MelwareDE | 795edc3b04 | |
MelwareDE | e97fd758b9 | |
MelwareDE | 85926f056a | |
MelwareDE | b42ada0ec9 | |
MelwareDE | 739a8dab38 | |
MelwareDE | 675bf55412 | |
MelwareDE | 8e476958b0 | |
MelwareDE | 233826121a | |
MelwareDE | 57708ed431 | |
MelwareDE | 0456bcc90c | |
MelwareDE | 48406de14c | |
MelwareDE | c65f9424b7 | |
MelwareDE | 73edae5356 | |
MelwareDE | 747b558087 | |
MelwareDE | 529b619d33 | |
MelwareDE | cfa7f41de0 | |
MelwareDE | 8c90073506 | |
MelwareDE | 24d3a90c5a | |
MelwareDE | d315cb6105 | |
MelwareDE | 0781e931c3 | |
MelwareDE | a5bff8162f | |
MelwareDE | 2605e06121 | |
MelwareDE | a59cdad65e | |
MelwareDE | 7eac23a7d6 | |
MelwareDE | 3d8b215153 | |
MelwareDE | 47f5786bed | |
MelwareDE | fcbc6d8caa | |
MelwareDE | 0c9abc7cbc | |
MelwareDE | 329d52d99f | |
MelwareDE | cf77a3577a | |
MelwareDE | ee3422402f | |
MelwareDE | 8b5d4bfc1b | |
MelwareDE | e8ad3f6455 | |
MelwareDE | ea1a3414bf | |
MelwareDE | ffc46df52c | |
MelwareDE | 30af5e14c1 | |
MelwareDE | 67380a24ae | |
MelwareDE | 11a6cb0e4a | |
MelwareDE | f13d666088 | |
MelwareDE | f045726aa5 | |
MelwareDE | 5a8db9b7aa | |
MelwareDE | 69da53451d | |
MelwareDE | bd11495d0b | |
MelwareDE | 39c9ac1475 | |
MelwareDE | 01df5d5ef3 | |
MelwareDE | b09d58c323 | |
MelwareDE | 170b200474 | |
MelwareDE | ea4a234fec | |
MelwareDE | 671c814ffd | |
MelwareDE | c81c4dd211 | |
MelwareDE | 1a786b1f16 | |
MelwareDE | 97e5e2406f | |
MelwareDE | ad4b6abc2f | |
MelwareDE | a1e2cfcd37 | |
MelwareDE | eb16251723 | |
MelwareDE | 7fe17bac31 | |
MelwareDE | 02562d0759 | |
MelwareDE | 2ad144f632 | |
MelwareDE | 01d4246d1d | |
MelwareDE | aca519ad3b | |
MelwareDE | c244d06aa9 | |
MelwareDE | ebc988a4cc | |
MelwareDE | 39f0b5ea1c | |
MelwareDE | 79ce55caf4 | |
MelwareDE | 865a974063 | |
MelwareDE | a0bf189dbc | |
MelwareDE | 0c961ad003 | |
MelwareDE | 47d4849bab | |
MelwareDE | 979d0b7c64 | |
MelwareDE | e9ef3dcb7f | |
MelwareDE | 4c82a964e3 | |
MelwareDE | da814a985e | |
MelwareDE | 9ba91f794a | |
MelwareDE | 9492241773 | |
MelwareDE | 3437c6cbd2 | |
MelwareDE | af3b9831ff | |
MelwareDE | b65153aae4 | |
MelwareDE | 5904d40121 | |
MelwareDE | 8d2a77021a | |
MelwareDE | 71d2a85b7f | |
MelwareDE | e1a398ca9e | |
MelwareDE | 7cdfac46a8 | |
MelwareDE | 0566d6fc7a | |
MelwareDE | edbbfe310c | |
MelwareDE | c8c07ae9a9 | |
MelwareDE | 646531ae38 | |
MelwareDE | 9520555d49 | |
MelwareDE | 1e15bbee22 | |
MelwareDE | cd9788c177 | |
MelwareDE | 38ea14fd46 | |
MelwareDE | 48ef87ff86 | |
MelwareDE | b78afd1938 | |
MelwareDE | 360550812f | |
MelwareDE | 1daf982ff6 | |
MelwareDE | 121b0ed7c8 | |
MelwareDE | 6c8b786a0d | |
MelwareDE | bc4d9179c5 | |
MelwareDE | 79bf35526b | |
MelwareDE | 35137fc921 | |
MelwareDE | 4c42d3fe26 | |
MelwareDE | d1d15d1365 | |
MelwareDE | e14113b5d7 | |
MelwareDE | 9dcf676b0c | |
MelwareDE | 06d1dce706 | |
MelwareDE | 5ab7650cfa | |
MelwareDE | 81afbf1f5c | |
MelwareDE | ae278ffa73 | |
MelwareDE | db92682c3a | |
MelwareDE | 4ed4f00f25 | |
MelwareDE | ffcf6757d6 | |
MelwareDE | be8968c915 | |
MelwareDE | ba89d59907 | |
MelwareDE | bf84177a4c | |
MelwareDE | 8a209fc690 | |
MelwareDE | 55de14b36c | |
MelwareDE | c657085a36 | |
MelwareDE | 1ca1e61aa4 | |
MelwareDE | 15a6b4c344 | |
MelwareDE | 4dd167bd29 | |
MelwareDE | 0427363a24 | |
MelwareDE | 6950b986ff | |
MelwareDE | c53df84210 | |
MelwareDE | 563494740a | |
MelwareDE | 6cb7e6f083 | |
MelwareDE | 00e394e220 | |
MelwareDE | ff1c4217c2 | |
MelwareDE | c2411cac82 | |
MelwareDE | eeff524567 | |
MelwareDE | 55e6bef4d4 | |
MelwareDE | ac80ecee49 | |
MelwareDE | 40015a959a | |
MelwareDE | eb7496a92b | |
MelwareDE | a0976a0f3e | |
MelwareDE | bbe14f0377 | |
MelwareDE | c3dd51a1c7 | |
MelwareDE | 57621e34ab | |
MelwareDE | 4b14aadd04 | |
MelwareDE | 62dd326709 | |
MelwareDE | 54ca760357 | |
MelwareDE | c9291ed2ff | |
MelwareDE | 08bea712d4 | |
MelwareDE | d2b4bdd349 | |
MelwareDE | b45e940762 | |
MelwareDE | b845700c4e | |
MelwareDE | c3304ad188 | |
MelwareDE | b3932bd8fa | |
MelwareDE | a835372f49 | |
MelwareDE | 451c093c9c | |
MelwareDE | a80ed136e6 | |
MelwareDE | e09aaa69d2 | |
MelwareDE | d17d02ab84 | |
MelwareDE | 10d1b89912 | |
MelwareDE | f2d362e203 | |
MelwareDE | 3c3a8ea6d6 | |
MelwareDE | 1ceaef4d15 | |
MelwareDE | cb12234f83 | |
MelwareDE | 42d240e32e | |
MelwareDE | 523d570e2d | |
MelwareDE | d58c5141f9 | |
MelwareDE | e47d614996 | |
MelwareDE | 25966a7046 | |
MelwareDE | e896d40153 | |
MelwareDE | a9c3419d9e | |
MelwareDE | 5ee344040d | |
MelwareDE | b832889dc7 | |
MelwareDE | 3cc0813e1e | |
MelwareDE | bde5812980 | |
MelwareDE | e567c800ca | |
MelwareDE | 66a3ad0ede | |
MelwareDE | 84550afacf | |
MelwareDE | a8c926e858 | |
MelwareDE | 1f87f1d416 | |
MelwareDE | 1bf477e35d | |
MelwareDE | bdbc804322 | |
MelwareDE | a1c472295f | |
MelwareDE | fb7189f483 | |
MelwareDE | 4432223953 | |
MelwareDE | dbcb09c244 | |
MelwareDE | cbb8bc5011 | |
MelwareDE | 63526d731a | |
MelwareDE | 4c1ebe93fa | |
MelwareDE | 9eac4f7df4 | |
MelwareDE | b0aa88eab0 | |
MelwareDE | 090192346b | |
MelwareDE | cb35b4aad2 | |
MelwareDE | 442186050c | |
MelwareDE | ab0108b92b | |
MelwareDE | 04528a3ea2 | |
MelwareDE | ce3e2d7017 | |
MelwareDE | 0708150113 | |
MelwareDE | f9799f6eb6 | |
MelwareDE | e2a5b417c7 | |
MelwareDE | 755ba51b12 | |
MelwareDE | 0423263179 | |
MelwareDE | 4474fba4a3 | |
MelwareDE | 0a8aa91742 | |
MelwareDE | a54f9e462e | |
MelwareDE | 75a4288341 | |
MelwareDE | a5b21aaf06 | |
MelwareDE | 3d81c6e7e9 | |
MelwareDE | 411ad13361 | |
MelwareDE | 620550e1e8 | |
MelwareDE | f24901822a | |
MelwareDE | d3e1e87183 | |
MelwareDE | aa385b1bca | |
MelwareDE | cb3a84b98f | |
MelwareDE | 3875d666f1 | |
MelwareDE | 8ec9a8f46a | |
MelwareDE | e8059e664b | |
MelwareDE | 6748df728f | |
MelwareDE | e483f336c0 | |
MelwareDE | 82c0e32f8a | |
MelwareDE | 03cb7d3048 | |
MelwareDE | 9ae64305da | |
MelwareDE | 850dfb503c | |
MelwareDE | 04e1dab784 | |
MelwareDE | d1ad040c4b | |
MelwareDE | af316c30d9 | |
MelwareDE | bb3bbe31d3 | |
MelwareDE | cae2b60cd4 | |
MelwareDE | 63c3da3a81 | |
MelwareDE | 7d31b498d0 | |
MelwareDE | 5452ed6952 | |
MelwareDE | de60f52c59 | |
MelwareDE | 873a1bf074 | |
MelwareDE | 00f2d3e198 | |
MelwareDE | e013fdd7f5 | |
MelwareDE | 4d614104eb | |
MelwareDE | ce8bda8195 | |
MelwareDE | d0c0964067 | |
MelwareDE | a25c5ee55c | |
MelwareDE | e120f854f0 | |
MelwareDE | 4136d39be1 | |
MelwareDE | b5119c8c71 | |
MelwareDE | dc4ee69fe9 | |
MelwareDE | 42c8474f71 | |
MelwareDE | 1d8e119c2c | |
MelwareDE | d00afc53d2 | |
MelwareDE | 8c558fc202 | |
MelwareDE | 5680639492 | |
MelwareDE | d87ba28a66 | |
MelwareDE | 4e4c406bb3 | |
MelwareDE | 5d8a77361f | |
MelwareDE | 67d2ac23ae | |
MelwareDE | 5228834b7d | |
MelwareDE | b222057cf2 | |
MelwareDE | d02004dabc | |
MelwareDE | 4c9b279ed0 | |
MelwareDE | 1b4680f969 | |
MelwareDE | 1b50367e34 | |
MelwareDE | 1b125d4d7e | |
MelwareDE | 2a56d9bf59 | |
MelwareDE | 9e7210d1de | |
MelwareDE | 47b9b750f1 | |
MelwareDE | 0c80e2361f | |
MelwareDE | 025d7c827c | |
MelwareDE | 117ae4eb13 | |
MelwareDE | ecf0c248af | |
MelwareDE | 1756447915 | |
MelwareDE | 892b24eb2a | |
MelwareDE | a13961713d | |
MelwareDE | 1a263e352a | |
MelwareDE | 2b907882eb | |
MelwareDE | 643081eb2f | |
MelwareDE | 625b1b6205 | |
MelwareDE | e5b84d2052 | |
MelwareDE | 767dd90bed | |
MelwareDE | 14abf19bb2 | |
MelwareDE | 246e5b21cb | |
MelwareDE | 1b95f0ca10 | |
MelwareDE | 7764d339cd | |
MelwareDE | 60f76b3c70 | |
MelwareDE | fd795e17da | |
MelwareDE | cadf4f5700 | |
MelwareDE | 131740cb89 | |
MelwareDE | e4e1beff0b | |
MelwareDE | ab87b13548 | |
MelwareDE | 92f26bd38b | |
MelwareDE | e9d1bbe5c5 | |
MelwareDE | 9d4968ab3a | |
MelwareDE | 04d4580bc4 | |
MelwareDE | cc90f574e6 | |
MelwareDE | b53dc5ad06 | |
MelwareDE | 3204ffe743 | |
MelwareDE | a9c2413461 | |
MelwareDE | cd18383e0e | |
MelwareDE | 76d0cae461 | |
MelwareDE | 5d65ee3566 | |
MelwareDE | 703088c8d6 | |
MelwareDE | aae199cb8c | |
MelwareDE | 638108e55e | |
MelwareDE | b13f9e3f29 | |
MelwareDE | d9d3efeee1 | |
MelwareDE | b21b7aacf7 | |
MelwareDE | 5685a6950e | |
MelwareDE | 84a99f0eda | |
MelwareDE | 4025bdf491 | |
MelwareDE | 0f92f2e02f | |
MelwareDE | 26f621aa78 | |
MelwareDE | cbd0547249 | |
MelwareDE | 0b76a06672 | |
MelwareDE | f50bb3fd2d | |
MelwareDE | 6bba2bbfc6 | |
MelwareDE | 3b730f1042 | |
MelwareDE | 8c812cee0c | |
MelwareDE | ebc059c0fc | |
MelwareDE | cd8e0d3dc2 | |
MelwareDE | 8c79f0d18a | |
MelwareDE | 0208255abd | |
MelwareDE | fa94aeac13 | |
MelwareDE | 35dc45003b | |
MelwareDE | d469965446 | |
MelwareDE | 6c19246b9d | |
MelwareDE | 92c3f4afc6 | |
MelwareDE | 6fc3803650 | |
MelwareDE | 096bacf541 | |
MelwareDE | d4d4ba020d | |
MelwareDE | 8ab15c6d47 | |
MelwareDE | 24081da912 | |
MelwareDE | 0b90a71fbc | |
MelwareDE | 220db2555e | |
MelwareDE | 81939e875d | |
MelwareDE | 6bd7dad3ec | |
MelwareDE | 7cda4d76bc | |
MelwareDE | 33b4cb4691 | |
MelwareDE | 5443bea1d9 | |
MelwareDE | df76b6a213 | |
MelwareDE | ec95d2e680 | |
MelwareDE | 9838ab6143 | |
MelwareDE | 676d8a428e | |
MelwareDE | 997ea1885e | |
MelwareDE | 61f051745e | |
MelwareDE | 2dc5e14116 | |
MelwareDE | f33a143924 | |
MelwareDE | 4914a97d30 | |
MelwareDE | a7b1c76d41 | |
MelwareDE | 6cb1871814 | |
MelwareDE | c84efdbce3 | |
MelwareDE | 2d3f679f96 | |
MelwareDE | a1b595d7a7 | |
MelwareDE | fe1232ce43 | |
MelwareDE | 57a5315566 | |
MelwareDE | 0c3801d3d3 | |
MelwareDE | 505ac93981 | |
MelwareDE | e7b931df5b | |
MelwareDE | 8b5ff59671 | |
MelwareDE | 2060adeeb1 | |
MelwareDE | e16c543423 | |
MelwareDE | 6e2e06ed21 | |
MelwareDE | 3ee93f995d | |
MelwareDE | 6e8a72ebe5 | |
MelwareDE | 5db1d9d1fe | |
MelwareDE | e536535139 | |
MelwareDE | 06135eb7dc | |
MelwareDE | ca207a4ded | |
MelwareDE | d8c24f23e9 | |
MelwareDE | e9b36aa1af | |
MelwareDE | c7ce547983 | |
MelwareDE | f0c812644d | |
MelwareDE | 5212533427 | |
MelwareDE | 8a0d8977be | |
MelwareDE | 25dceb2571 | |
MelwareDE | 2f3a449f5b | |
MelwareDE | 8365b305c5 | |
MelwareDE | 333d4bffdc | |
MelwareDE | 1d00abbdfc | |
MelwareDE | 218782c4f8 | |
MelwareDE | 96364f485d | |
MelwareDE | 32e06de3b8 | |
MelwareDE | 658b23282d | |
MelwareDE | 28b28e7eeb | |
MelwareDE | a7643a747a | |
MelwareDE | eed0604798 | |
MelwareDE | c6d777d26a | |
MelwareDE | 881ff2c02b | |
MelwareDE | 5ef8dd4426 | |
MelwareDE | 1d6156f52f | |
MelwareDE | 3a6f500ccc | |
MelwareDE | 66529db156 | |
MelwareDE | ddee6aff05 | |
MelwareDE | dbde64eb4d | |
MelwareDE | 091f8c63df | |
MelwareDE | c861a2676b | |
MelwareDE | 763dc2ec31 | |
MelwareDE | 705e0e5d84 | |
MelwareDE | d3b162066a | |
MelwareDE | 1b5f560431 | |
MelwareDE | b7f8b51ae0 | |
MelwareDE | 21cd8a4c91 | |
MelwareDE | 87e61975cc | |
MelwareDE | 57e9fb7e44 | |
MelwareDE | fa80b541a7 | |
MelwareDE | 465651bf11 | |
MelwareDE | 939cf7615b | |
MelwareDE | dcfcefc4ab | |
MelwareDE | 63ea97c952 | |
MelwareDE | 5a720165ff | |
MelwareDE | 3f7ebcd177 | |
MelwareDE | 172eb91fb0 | |
MelwareDE | 8d8020949e | |
MelwareDE | c56504fd7b | |
MelwareDE | 25852cfcf5 | |
MelwareDE | 407e678cb4 | |
MelwareDE | f4fe1dc73f | |
MelwareDE | 5827ebfedb | |
MelwareDE | c3cc336d96 | |
MelwareDE | f1318438d3 | |
MelwareDE | 0b5ff0dd0f | |
MelwareDE | 0447547c55 | |
MelwareDE | 2004dd14b4 | |
MelwareDE | 705a9807f5 | |
MelwareDE | a1d2cbdc52 | |
MelwareDE | 254f20521e | |
MelwareDE | badd38d9a2 | |
MelwareDE | befe1c83f1 | |
MelwareDE | 23973edf04 | |
MelwareDE | 784a628015 | |
MelwareDE | 3d4e19f50c | |
MelwareDE | 4f14c385ae | |
MelwareDE | d1f147ffe8 | |
MelwareDE | e9bc5965a4 | |
MelwareDE | 286435c900 | |
MelwareDE | dafad9727e | |
MelwareDE | 6780755b7c | |
MelwareDE | e2da85d7fe | |
MelwareDE | 316eebf9ee | |
MelwareDE | 059bdfe0df | |
MelwareDE | 2dbc99f5b2 | |
MelwareDE | 1742806313 | |
MelwareDE | 620556efd6 | |
MelwareDE | fdc7448269 | |
MelwareDE | a1f9a32839 | |
MelwareDE | 192b57024b | |
MelwareDE | 944a643786 | |
MelwareDE | 1aecef90dc | |
MelwareDE | bacf848e77 | |
MelwareDE | 4d71e8690b | |
MelwareDE | 9671c6df5c | |
MelwareDE | a662db2864 | |
MelwareDE | ddede6383f | |
MelwareDE | a5239eea72 | |
MelwareDE | 8080bf65ac | |
MelwareDE | c522111bf3 | |
MelwareDE | 68686fc241 | |
MelwareDE | 27b01dea2d | |
MelwareDE | 74d8763401 | |
MelwareDE | 0d75a3e5af | |
MelwareDE | 69d0731ead | |
MelwareDE | 02cf3834d9 | |
MelwareDE | 3d316a8ab5 | |
MelwareDE | 6a50aeb45e | |
MelwareDE | 380d705858 | |
MelwareDE | 57207fb2bd | |
MelwareDE | 7f8662840f | |
MelwareDE | db0382894a | |
MelwareDE | 602aa043aa | |
MelwareDE | 936d3471d2 | |
MelwareDE | 07ef86e3f4 | |
MelwareDE | f16608c7eb | |
MelwareDE | 1a9d34ed47 | |
MelwareDE | ce15487de7 | |
MelwareDE | c828da398a | |
MelwareDE | b18c166ecf | |
MelwareDE | bd1f4faaba | |
MelwareDE | e3aa68029c | |
MelwareDE | 7cf9ec0839 | |
MelwareDE | b307540b1d | |
MelwareDE | e7380a0a30 | |
MelwareDE | 2c08548968 | |
MelwareDE | 217b54f1d0 | |
MelwareDE | bdb37f1df9 | |
MelwareDE | 00b57d574b | |
MelwareDE | 3f5395c6d9 | |
MelwareDE | 2ecb9846cb | |
MelwareDE | 8cc530b42c | |
MelwareDE | 63ff8d3039 | |
MelwareDE | 7d60ab7fa0 | |
MelwareDE | 1162c1d76b | |
MelwareDE | 30081ce75d | |
MelwareDE | 3596c01726 | |
MelwareDE | 1fd9eeb255 | |
MelwareDE | b2e9940ddd | |
MelwareDE | bba36b630c | |
MelwareDE | 62e5876536 | |
MelwareDE | 1e1d630071 | |
MelwareDE | 30bc33755b | |
MelwareDE | 9f350c412a | |
MelwareDE | 51572a7626 | |
MelwareDE | 62fe88239b | |
MelwareDE | fc6ebf863b | |
MelwareDE | 0c6ebce107 | |
MelwareDE | ae8f7fecd6 | |
MelwareDE | 85a8f1a68d | |
MelwareDE | 6c431378fc | |
MelwareDE | 160587cf06 | |
MelwareDE | cdb1fc1592 | |
MelwareDE | 76c580033a | |
MelwareDE | a20a41e87d | |
MelwareDE | 21c41bd6b2 | |
MelwareDE | e6d47e7ecf | |
MelwareDE | 6085b31e81 | |
MelwareDE | 51b5310f70 | |
MelwareDE | 1d54326696 | |
MelwareDE | 21cce7a3e8 |
|
@ -1,2 +0,0 @@
|
|||
.version
|
||||
config.h
|
262
CHANGES
262
CHANGES
|
@ -1,6 +1,252 @@
|
|||
CHANGES
|
||||
=======
|
||||
|
||||
HEAD
|
||||
------------------
|
||||
- refuse to reload on active channels
|
||||
- ast_devstate_changed() changes with new cache argument
|
||||
- check for bchannel information element on incoming call
|
||||
- added 't' option to select in-band tones available indication as Q.931
|
||||
(thanks to Maciej S. Szmigiero <mail@maciej.szmigiero.name>)
|
||||
- support for Asterisk 13 (thanks to Michael Kuron <m.kuron@gmx.de>)
|
||||
- fixed check of asterisk version with asterisk binary if another install path is used.
|
||||
- remove codec 'none' from translation path which prevents bridge.
|
||||
|
||||
|
||||
chan_capi-1.1.6
|
||||
------------------
|
||||
- Asterisk 1.8 changes
|
||||
- added dialplan variables ISDNPI1 and ISDNPI2
|
||||
- Support for 'divastreaming' available (Diva 4PRI PCI, Diva 2PRI PCI,
|
||||
Diva 4PRI HS PCIe, Diva 2PRI HS PCIe, Diva 1PRI HS PCIe,
|
||||
Diva 8PRI PCIe FS, Diva 4PRI PCIe FS)
|
||||
- Fixed memory leak in chat_play if using with 's' option
|
||||
- Add 'econtransitconn' configurations parameter. Allows to preserve
|
||||
EC for transit connections
|
||||
- added variable DISCONNECT_IND_REASON to get real reason code from CAPI
|
||||
- added capicommand(keypad)
|
||||
- added log of FACILITY_IND for call deflect suplementary service
|
||||
- malloc,strdup,free -> ast_(malloc,strdup,free)
|
||||
- Use Diva streaming for NULL PLCI and for resource PLCI
|
||||
- Resolved http://www.ipphoneforum.eu/showthread.php?t=220051
|
||||
- Use Diva QSIG CAPI extensions for processing of Calling Party Name
|
||||
- Add Slinear
|
||||
- Add HD voice using G.722, Siren7, Siren14 and Slinear16
|
||||
- added faxdestination= to capi.conf to configure custom context,exten,prio.
|
||||
- allow capicommand option separator "|" and ",".
|
||||
- Add MWI server
|
||||
- Add MWI client
|
||||
- Improved call distribution algorithm for outgoing calls
|
||||
- Add 'capi ifcstate', 'capi exec', 'capi show resources' and
|
||||
'chat manage remove' CLI commands
|
||||
- Add AMI 'Capichat[List,Mute,Unmute,Remove]' and 'CapiCommand' actions and
|
||||
Capichat[List,ListComplete,Join,Leave,End] events
|
||||
- Add device state events for char rooms (capichat:[roomname]) and for
|
||||
interface state (ISDN/I[N]/congestion)
|
||||
- Add access to Diva trace driver
|
||||
|
||||
chan_capi-1.1.5
|
||||
------------------
|
||||
- corrected check for Info value on CONNECT_B3_CONF
|
||||
- fixed NULL-pointer in cid_name (asterisk 1.6 pickup revealed this)
|
||||
- changed action on prodding in .write function to ignore it
|
||||
- API adaptions to new asterisk trunk
|
||||
|
||||
chan_capi-1.1.4
|
||||
------------------
|
||||
- use extended fax if available only and have fine resolution on receive activated by default
|
||||
- fixed chat error on creating third chat-room
|
||||
|
||||
chan_capi-1.1.3
|
||||
------------------
|
||||
- fixed buffer length error with internal libcapi debug code.
|
||||
- performance optimizations, use debug code when needed only.
|
||||
- added commands for media features supported by Dialogic(R) Diva(R) Media Boards
|
||||
- added variable CAPI_CIP for full access to all bearer capabilities.
|
||||
- fixed CAPI 'chat' for using more than 8 controllers.
|
||||
- fixed CAPI 'chat' for not exceeding maximal size of CAPI message
|
||||
- add color fax
|
||||
- add autodetection of fax file format for sendfax command (SFF, CFF JPEG, CFF T.43, TEXT)
|
||||
- add extension for FAX paper formats and resolutions
|
||||
- adjust NULL PLCI LI path
|
||||
- add resource PLCI
|
||||
- add echocancelpath configuration option
|
||||
- fixed possible race condition while waiting for DISCONNECT_CONF
|
||||
- add static half duplex conference
|
||||
- add dynamic half duplex conference
|
||||
- add clear channel fax
|
||||
- add DTMF detection for NULL PLCI
|
||||
- use direct access to vocoders without RTP framing
|
||||
- play message to conference and music on hold to caller
|
||||
- add commands to remove users from chat
|
||||
- allow to specity the 'ETS 300 102-1' called party number octet 3
|
||||
- fixed possible buffer overflow in 'deflect'
|
||||
- added 'h' option to chat to auto-hangup caller if alone in conference too long
|
||||
|
||||
|
||||
chan_capi-1.1.2
|
||||
------------------
|
||||
- added config setting 'faxdetecttime' to limit the fax detection for a given amount of seconds.
|
||||
- added config option for subscriber prefix. Some lines may show local calls without area code
|
||||
signaled as subscriber-number. Here the complete prefix including area code must be added.
|
||||
- better counting of active B-channels.
|
||||
- make capicommand(progress) "early-B3" usable for non NT-mode incoming channels as well.
|
||||
- support early Line-Interconnect (bridge) as soon as both B-channels are up. This bridges B-channels
|
||||
from beginning of the call-establishment, even before calls are connected and the bridge command is received.
|
||||
The dial() option 'G' is used to activate this feature.
|
||||
- fixed big-endian issue for DATA_B3 messages in internal libcapi code.
|
||||
- fixed NULL-pointer when no digits are signaled in DID mode.
|
||||
- adapt to new Asterisk 1.6.1 changes.
|
||||
- added capicommand to set CAPI application ID into an Asterisk dialplan variable.
|
||||
|
||||
|
||||
chan_capi-1.1.1
|
||||
------------------
|
||||
- fixed controller count when creating NULL-PLCI interface.
|
||||
- simplified check for unused controller.
|
||||
|
||||
|
||||
chan_capi-1.1.0
|
||||
------------------
|
||||
- send local DATE/TIME with CONNECT when in NT-mode.
|
||||
- added transfergroup config option to set controllers allowed for transfer.
|
||||
- send Sending-Complete if overlap dialing is not used.
|
||||
- fixed numberingplan for 'connected number'.
|
||||
- added devicestate option.
|
||||
- capi-chat can play music-on-hold for first caller.
|
||||
- adapt to new asterisk 1.6 API
|
||||
- fixed reading capi profile on big-endian
|
||||
- increased maximum number of CAPI controllers to 64 (needed for big PBX).
|
||||
- if immediate=yes is set in DID mode, accept calls to empty DNID (needed for Austrian lines).
|
||||
- use own libcapi20 implementation by default (no library for CAPI is needed any more).
|
||||
|
||||
chan_capi-1.0.2
|
||||
------------------
|
||||
- possibly fixed ECT channel hang
|
||||
- added 'x' option to capicommand(ect) to have real 'explicit call transfer'
|
||||
(needed by some ISDN lines)
|
||||
- support CCBS (call completion on busy subscriber)
|
||||
- added capicommand(chat) for CAPI-based MeetMe/Conference using onboard DSPs.
|
||||
- fixed ton-display in 'show capi channels' on outgoing line.
|
||||
- fix for 64bit support
|
||||
- Asterisk 1.4.4 adaptions
|
||||
- send 'In-band info available' for progress in NT-mode
|
||||
- detect KEYPAD digits in NT-mode and send call to 'K...' extension
|
||||
- fixed possible deadlock when answering a just disconnected call
|
||||
|
||||
|
||||
chan_capi-1.0.1
|
||||
------------------
|
||||
- added qsig caller-name patch by Mario Goegel
|
||||
- recognize asterisk 1.4.1
|
||||
- register at CAPI with needed maxLogicalConnections only
|
||||
- do not send SELECT_B_PROTOCOL more than once
|
||||
- do not send more DATA_B3 messages than allowed by CAPI_MAX_B3_BLOCKS
|
||||
- added 'k' option to capi receivefax command for not deleting bad faxes
|
||||
- added B-channel number to channel name for better identification
|
||||
- added variable setting REDIRECTIONNUMBER on outgoing call
|
||||
- fixed deadlock with ast_async_goto on fax tone detection
|
||||
- listen to CAPI supplementary information
|
||||
QSIG:
|
||||
- added support for different qsig variants
|
||||
- added support for rerouting informations on incoming calls
|
||||
- added implementation of Simple Call Transfer
|
||||
|
||||
chan_capi-1.0.0
|
||||
------------------
|
||||
- Added preliminary handling of MANUFACTURER_IND.
|
||||
- Check for fax connection when in receivefax mode before writing data
|
||||
to file.
|
||||
- Try to detect for generic jitter buffer patch
|
||||
- Adapted to new Asterisk version 1.4 (Bug PR#20)
|
||||
- Adapted to new ast_channel_alloc from asterisk trunk.
|
||||
- Make capicommand(echocancel) setting non-permanent.
|
||||
Setting is restored after hangup.
|
||||
- Better check for asterisk version 1.4 BUG#23
|
||||
- Added information and changed example for tx/rx gains.
|
||||
- Read the channel frames during wait for fax finish.
|
||||
- Added progress when in faxmode to wakeup asterisk-1.2.
|
||||
(needed for e.g. auto-hangup on timeout)
|
||||
- Do not error on invalid controller in capi.conf, just ignore it.
|
||||
- Added 3PTY patch by Simon Peter.
|
||||
- Allow echo-cancel even with old CAPI configuration bit for
|
||||
echo-cancel.
|
||||
- Fix compiler warnings.
|
||||
- Fixed callerid on incoming call with Asterisk 1.4 (PR#25)
|
||||
- Remove possible race condition in with hangup and DISCONNECT_IND.
|
||||
- Rixed gain and echosquelch use according to transfercapability.
|
||||
- Do not wait for DISCONNECT_B3_CONF in activehangup.
|
||||
- Reset PLCI on DISCONNECT_IND to avoid race if asterisk is too slow
|
||||
with hangup command.
|
||||
- Added Asterisk 1.4 jitterbuffer usage.
|
||||
- Fixed compiler warning with Asterisk 1.4.0
|
||||
- Added music-on-hold on HOLD request for Asterisk 1.4
|
||||
|
||||
chan_capi-0.7.1
|
||||
------------------
|
||||
- Set FAXREASONTEXT to "OK" instead of empty string.
|
||||
- Disconnect reason 0x3400 is treated as 'successful' in faxmode.
|
||||
- use CIP speech as default if transfercapability is unkown.
|
||||
- set correct channel/cdr status in fax mode too.
|
||||
- Use correct interface to wait on for ECT facility.
|
||||
|
||||
chan_capi-0.7.0
|
||||
------------------
|
||||
- added amaflags
|
||||
- added pickupgroup (internal pickup with pickupexten)
|
||||
- added capicommand(sendfax)
|
||||
- dropped compatiblity to versions before Asterisk-1.2.0
|
||||
- added capicommand(echocancel)
|
||||
- added CAPI RTP (Eicon DIVA Server cards can do that)
|
||||
- added new cli 'capi show channels'
|
||||
- a lot of fixes
|
||||
|
||||
chan_capi-cm-0.6.5
|
||||
------------------
|
||||
- fixed compilation with Asterisk 1.0.7
|
||||
- fixed call deflect if number is longer
|
||||
- removed function VANITYNUMBER, this does not belong into channel drivers
|
||||
|
||||
chan_capi-cm-0.6.4
|
||||
------------------
|
||||
- do not do echo-squelch or gain if transfercapability is non-voice
|
||||
- fix deadlock when changing to fax mode
|
||||
- better capi message handling
|
||||
- removed double memset to zero
|
||||
- use safer copy_string function
|
||||
- removed unneeded lockB3q
|
||||
- avoid capi message number zero
|
||||
- added locking rules
|
||||
- fix ECT (use implicit ECT)
|
||||
- fixed setting language for each interface
|
||||
- fix wait for b-channel to go down on ECT.
|
||||
|
||||
chan_capi-cm-0.6.3
|
||||
------------------
|
||||
- fixed buffer overflow in overlap dial
|
||||
- remove some compiler warnings
|
||||
|
||||
chan_capi-cm-0.6.2
|
||||
------------------
|
||||
- set some info variables when receiving fax
|
||||
- added language support
|
||||
- prepared devicestate(hint) support
|
||||
- do not change early-B3 setting on conf error for CONNECT_B3
|
||||
- small fixes in Makefile targets (thanks to Karsten Keil)
|
||||
- do not send audio to local exchange when in TE-mode.
|
||||
- fix missing CONF messages when no interface is found
|
||||
- small transfercap and overlapdial fix
|
||||
- do not forward DTMF if in NT-mode and the line is not yet connected
|
||||
- fixed line interconnect
|
||||
- B-channel handling better
|
||||
- NT-mode progress
|
||||
- removed deadlock in faxreceive.
|
||||
- initialize variable ocid
|
||||
- correct use of timeoutms in native bridge
|
||||
- use more common defines for mutex_lock/unlock and _log()
|
||||
- clean up and OpenPBX portability.
|
||||
- adapted to latest asterisk bridge function prototype.
|
||||
|
||||
chan_capi-cm-0.6.1
|
||||
------------------
|
||||
- fixed setting of redirecting number rdnis instead of cid.
|
||||
|
@ -10,26 +256,26 @@ chan_capi-cm-0.6.1
|
|||
used if dial option 'd' is specified.
|
||||
- moved ast_softhangup() out of interface lock
|
||||
- use correct mutex_init call for interface lock
|
||||
- when 'o' option is used for overlap dialing, don't send any digits
|
||||
- when 'o' option is used for overlap dialing, do not send any digits
|
||||
with the CONNECT_REQ. This gives better progress together with 'b'.
|
||||
- create a pseudo channel for each interface for incoming signalling
|
||||
without B-channel.
|
||||
- added channel locks
|
||||
- fixed capi init order (thanks to Hans Petter Selasky)
|
||||
- fixed did handling
|
||||
- fixed CAPI init order (thanks to Hans Petter Selasky)
|
||||
- fixed DID handling
|
||||
- set RDNIS if redirecting number was received.
|
||||
- simplified call to ast_exists_extension()
|
||||
- when check for valid extension, check the callerid as well
|
||||
- changed call-waiting and deflect handling in CONNECT_IND
|
||||
- use 'immediate' config in MSN mode, if pbx shall be started on
|
||||
- use 'immediate' config in MSN mode, if PBX shall be started on
|
||||
CONNECT_IND and shall not wait until SETUP/SENDING-COMPLETE was received.
|
||||
Since info like REDIRECTINGNUMBER will come after CONNECT_IND, this may
|
||||
be lost then. But for some drivers/telcos/pbx, this setting is needed.
|
||||
- fix start of line interconnect in old mode.
|
||||
- start early-b3 on PROCEEDING too.
|
||||
- don't send audio data, if in fax receive mode
|
||||
- do not send audio data, if in fax receive mode
|
||||
- disconnect on finished fax immediately
|
||||
- don't run through gain list, if gain is 1.0.
|
||||
- do not run through gain list, if gain is 1.0.
|
||||
- use correct A-law idle value.
|
||||
- removed old example from capi.conf
|
||||
|
||||
|
@ -61,12 +307,12 @@ chan_capi-cm-0.6
|
|||
- receive a fax via CAPI is now done with capicommand(receivefax|...) and added stationid...
|
||||
- fixed call-deflection and moved this feature from separate application
|
||||
to capicommand().
|
||||
- added config option 'immediate' to start pbx if no dnid has been received yet.
|
||||
- added config option 'immediate' to start PBX if no dnid has been received yet.
|
||||
- endian fixes
|
||||
- compile fixes with newer Asterisk
|
||||
- update channel name on did changes.
|
||||
- support 'type of number' (numbering-plan).
|
||||
- U-Law setting is now done in capi.conf instead of Makefile define.
|
||||
- u-Law setting is now done in capi.conf instead of Makefile define.
|
||||
- allow using interface name in Dial().
|
||||
- on hangup, use hangupcause from other channel or from var PRI_CAUSE.
|
||||
- improved DID handling on PtP connections.
|
||||
|
|
29
INSTALL
29
INSTALL
|
@ -4,20 +4,39 @@ INSTALL
|
|||
Modify the Makefile to fit your system, especially the path to the Asterisk
|
||||
include files.
|
||||
|
||||
To build the driver you will need an installed capi system, including header
|
||||
To build the driver you will need an installed CAPI system, including header
|
||||
files.
|
||||
|
||||
To build the channel driver:
|
||||
By default, an internal version of libcapi20 is used (you do not need libcapi20 to
|
||||
be installed on your system). If you do not want this and the installed libcapi20
|
||||
should be used, add the option
|
||||
USE_OWN_LIBCAPI=no
|
||||
to the 'make' command.
|
||||
|
||||
To build from/for other Asterisk sources (default is '/' where /usr/include/asterisk
|
||||
is expected), add option
|
||||
INSTALL_PREFIX=<where your /usr/include/asterisk is>
|
||||
to 'make' command. This makes also sense when compiling for other targets or when
|
||||
cross compiling.
|
||||
|
||||
|
||||
To build the channel module:
|
||||
---------------------------------
|
||||
make
|
||||
|
||||
For verbose compiling:
|
||||
---------------------------------
|
||||
make V=1
|
||||
|
||||
|
||||
To install:
|
||||
----------------
|
||||
make install
|
||||
|
||||
|
||||
To install a sample configuration:
|
||||
----------------------------------
|
||||
make config
|
||||
make install_config
|
||||
|
||||
|
||||
In /etc/asterisk/modules.conf insert the line:
|
||||
|
@ -26,5 +45,5 @@ In /etc/asterisk/modules.conf insert the line:
|
|||
and in the [global] section:
|
||||
chan_capi.so=yes
|
||||
|
||||
HEY, don't forget a trailing newline at the end of modules.conf!!!
|
||||
|
||||
Don't forget a trailing newline at the end of modules.conf!
|
||||
|
||||
|
|
160
Makefile
160
Makefile
|
@ -1,11 +1,9 @@
|
|||
#
|
||||
# (CAPI*)
|
||||
#
|
||||
# An implementation of Common ISDN API 2.0 for Asterisk
|
||||
#
|
||||
# Makefile, based on the Asterisk Makefile, Coypright (C) 1999, Mark Spencer
|
||||
#
|
||||
# Copyright (C) 2005 Cytronics & Melware
|
||||
# Copyright (C) 2005-2009 Cytronics & Melware
|
||||
#
|
||||
# Armin Schindler <armin@melware.de>
|
||||
#
|
||||
|
@ -20,8 +18,16 @@
|
|||
|
||||
OSNAME=${shell uname}
|
||||
|
||||
DIVA_STREAMING=0
|
||||
DIVA_STATUS=0
|
||||
DIVA_VERBOSE=0
|
||||
|
||||
USE_OWN_LIBCAPI=yes
|
||||
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
|
||||
V=0
|
||||
|
||||
INSTALL_PREFIX=
|
||||
|
||||
ASTERISK_HEADER_DIR=$(INSTALL_PREFIX)/usr/include
|
||||
|
@ -34,8 +40,6 @@ ifeq (${OSNAME},NetBSD)
|
|||
ASTERISK_HEADER_DIR=$(INSTALL_PREFIX)/usr/pkg/include
|
||||
endif
|
||||
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then if [ -f CVS/Tag ] ; then echo "CVS-`sed 's/^T//g' CVS/Tag`-`date +"%D-%T"`"; else echo "CVS-HEAD-`date +"%D-%T"`"; fi; fi; fi)
|
||||
|
||||
MODULES_DIR=$(INSTALL_PREFIX)/usr/lib/asterisk/modules
|
||||
|
||||
ifeq (${OSNAME},FreeBSD)
|
||||
|
@ -46,24 +50,85 @@ ifeq (${OSNAME},NetBSD)
|
|||
MODULES_DIR=$(INSTALL_PREFIX)/usr/pkg/lib/asterisk/modules
|
||||
endif
|
||||
|
||||
CONFIG_DIR=$(INSTALL_PREFIX)/etc/asterisk
|
||||
|
||||
ifeq (${OSNAME},FreeBSD)
|
||||
CONFIG_DIR=$(INSTALL_PREFIX)/usr/local/etc/asterisk
|
||||
endif
|
||||
|
||||
ifeq (${OSNAME},NetBSD)
|
||||
CONFIG_DIR=$(INSTALL_PREFIX)/usr/pkg/etc/asterisk
|
||||
endif
|
||||
|
||||
OSARCH=$(shell uname -s)
|
||||
|
||||
ifeq ($(strip $(PROC)),)
|
||||
ifeq (${OSARCH},Linux)
|
||||
PROC=$(shell uname -m)
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
PROC=$(shell uname -m)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
AVERSION=$(shell if grep -q "VERSION_NUM 0104" $(ASTERISK_HEADER_DIR)/asterisk/version.h; then echo V1_4; fi 2>/dev/null)
|
||||
|
||||
ifeq (${USE_OWN_LIBCAPI},yes)
|
||||
INCLUDE= -I./libcapi20
|
||||
LIBLINUX=
|
||||
else
|
||||
INCLUDE=
|
||||
LIBLINUX=-lcapi20
|
||||
endif
|
||||
|
||||
ifeq (${DIVA_STREAMING},1)
|
||||
INCLUDE += -I./divastreaming -I./divastreaming/..
|
||||
endif
|
||||
|
||||
ifeq (${DIVA_STATUS},1)
|
||||
INCLUDE += -I./divastatus -I./divastatus/..
|
||||
endif
|
||||
|
||||
INCLUDE += -I./divaverbose
|
||||
|
||||
DEBUG=-g #-pg
|
||||
INCLUDE=-I$(ASTERISK_HEADER_DIR)
|
||||
INCLUDE+= -I$(ASTERISK_HEADER_DIR)
|
||||
ifndef C4B
|
||||
ifeq (${OSNAME},FreeBSD)
|
||||
INCLUDE+=$(shell [ -d /usr/include/i4b/include ] && \
|
||||
INCLUDE+= $(shell [ -d /usr/include/i4b/include ] && \
|
||||
echo -n -I/usr/include/i4b/include)
|
||||
endif
|
||||
ifeq (${OSNAME},NetBSD)
|
||||
INCLUDE+=$(shell [ -d /usr/include/i4b/include ] && \
|
||||
INCLUDE+= $(shell [ -d /usr/include/i4b/include ] && \
|
||||
echo -n -I/usr/include/i4b/include)
|
||||
endif
|
||||
CFLAGS=-pipe -fPIC -Wall -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE
|
||||
CFLAGS+=-O6
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||
endif #C4B
|
||||
|
||||
ifdef C4B
|
||||
LIBLINUX+=-L/usr/local/lib -llinuxcapi20
|
||||
endif
|
||||
|
||||
CFLAGS=-pipe -fPIC -Wall -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
CFLAGS+=-Wno-unused-but-set-variable
|
||||
CFLAGS+=-O2
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
CFLAGS+=$(shell if uname -m | grep -q "ppc\|arm\|s390"; then echo "-fsigned-char"; fi)
|
||||
ifeq (${DIVA_STREAMING},1)
|
||||
CFLAGS += -DDIVA_STREAMING=1
|
||||
endif
|
||||
ifeq (${DIVA_STATUS},1)
|
||||
CFLAGS += -DDIVA_STATUS=1
|
||||
|
||||
CFLAGS+=$(shell echo '\#include <sys/inotify.h>' > /tmp/test.c 2>/dev/null && \
|
||||
echo 'int main(int argc,char**argv){if(inotify_init()>=0)return 0; return 1;}' >> /tmp/test.c 2>/dev/null && \
|
||||
$(CC) /tmp/test.c -o /tmp/test && /tmp/test >/dev/null 2>&1 && echo '-DCC_USE_INOTIFY=1'; rm -f /tmp/test.c /tmp/test)
|
||||
endif
|
||||
ifeq (${DIVA_VERBOSE},1)
|
||||
CFLAGS += -DDIVA_VERBOSE=1
|
||||
endif
|
||||
|
||||
CFLAGS+=-DASTERISKVERSION=\"$(ASTERISKVERSION)\"
|
||||
|
||||
LIBS=-ldl -lpthread -lm
|
||||
CC=gcc
|
||||
|
@ -71,29 +136,86 @@ INSTALL=install
|
|||
|
||||
SHAREDOS=chan_capi.so
|
||||
|
||||
OBJECTS=chan_capi.o c20msg.o
|
||||
OBJECTS=chan_capi.o chan_capi_utils.o chan_capi_rtp.o chan_capi_command.o xlaw.o dlist.o \
|
||||
chan_capi_qsig_core.o chan_capi_qsig_ecma.o chan_capi_qsig_asn197ade.o \
|
||||
chan_capi_qsig_asn197no.o chan_capi_supplementary.o chan_capi_chat.o \
|
||||
chan_capi_mwi.o chan_capi_cli.o chan_capi_ami.o chan_capi_management_common.o \
|
||||
chan_capi_devstate.o
|
||||
|
||||
ifeq (${USE_OWN_LIBCAPI},yes)
|
||||
OBJECTS += libcapi20/convert.o libcapi20/capi20.o libcapi20/capifunc.o
|
||||
endif
|
||||
|
||||
ifeq (${DIVA_STREAMING},1)
|
||||
OBJECTS += divastreaming/diva_streaming_idi_host_ifc_impl.o \
|
||||
divastreaming/diva_streaming_idi_host_rx_ifc_impl.o \
|
||||
divastreaming/diva_streaming_manager.o \
|
||||
divastreaming/diva_streaming_messages.o \
|
||||
divastreaming/segment_alloc.o \
|
||||
divastreaming/chan_capi_divastreaming_utils.o \
|
||||
divastreaming/runtime.o
|
||||
endif
|
||||
|
||||
ifeq (${DIVA_STATUS},1)
|
||||
OBJECTS += divastatus/divastatus.o
|
||||
endif
|
||||
|
||||
ifeq (${DIVA_VERBOSE},1)
|
||||
OBJECTS += divaverbose/divaverbose.o
|
||||
endif
|
||||
|
||||
CFLAGS+=-Wno-missing-prototypes -Wno-missing-declarations
|
||||
|
||||
CFLAGS+=-DCRYPTO
|
||||
|
||||
ifneq (${AVERSION},V1_4)
|
||||
CFLAGS+=`if grep -q AST_JB config.h; then echo -DAST_JB; fi`
|
||||
endif
|
||||
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
all: config.h $(SHAREDOS)
|
||||
|
||||
clean:
|
||||
rm -f config.h
|
||||
rm -f *.so *.o
|
||||
rm -f libcapi20/*.o
|
||||
rm -f divastreaming/*.o
|
||||
rm -f divastatus/*.o
|
||||
rm -f divaverbose/*.o
|
||||
|
||||
distclean: clean
|
||||
rm -f $(MODULES_DIR)/$(SHAREDOS)
|
||||
|
||||
sysclean: distclean
|
||||
rm -f $(MODULES_DIR)/*.so
|
||||
|
||||
config.h:
|
||||
./create_config.sh "$(ASTERISK_HEADER_DIR)"
|
||||
|
||||
chan_capi.so: $(OBJECTS)
|
||||
$(CC) -shared -Xlinker -x -o $@ $^ -lcapi20
|
||||
.c.o: config.h
|
||||
@if [ "$(V)" = "0" ]; then \
|
||||
echo " [CC] $*.c -> $*.o"; \
|
||||
else \
|
||||
echo "$(CC) $(CFLAGS) -c $*.c -o $*.o"; \
|
||||
fi
|
||||
@$(CC) $(CFLAGS) -c $*.c -o $*.o;
|
||||
|
||||
$(SHAREDOS): $(OBJECTS)
|
||||
@if [ "$(V)" = "0" ]; then \
|
||||
echo " [LD] $@ ($^)"; \
|
||||
else \
|
||||
echo "$(CC) -shared -Xlinker -x -o $@ $^ $(LIBLINUX)"; \
|
||||
fi
|
||||
@$(CC) -shared -Xlinker -x -o $@ $^ $(LIBLINUX)
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d -m 755 $(MODULES_DIR)
|
||||
for x in $(SHAREDOS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
|
||||
|
||||
config: all
|
||||
cp capi.conf $(INSTALL_PREFIX)/etc/asterisk/
|
||||
install_config: capi.conf
|
||||
$(INSTALL) -d -m 755 ${CONFIG_DIR}
|
||||
$(INSTALL) -m 644 capi.conf ${CONFIG_DIR}
|
||||
|
||||
samples: config
|
||||
samples: install_config
|
||||
|
||||
|
|
446
README
446
README
|
@ -1,16 +1,12 @@
|
|||
(CAPI*) chan_capi a Common ISDN API 2.0 implementation
|
||||
for Asterisk/OpenPBX
|
||||
chan_capi a Common ISDN API 2.0 implementation for Asterisk
|
||||
|
||||
Copyright (C) 2005 Cytronics & Melware
|
||||
Copyright (C) 2005-2010 Cytronics & Melware
|
||||
Armin Schindler <armin@melware.de>
|
||||
|
||||
Reworked, but based on the work of
|
||||
Copyright (C) 2002-2005 Junghanns.NET GmbH
|
||||
Klaus-Peter Junghanns <kpj@junghanns.net>
|
||||
|
||||
Ported to OpenPBX.org 22nd October 2004,
|
||||
Rob Thomas, <xrobau@gmail.com>
|
||||
|
||||
This program is free software and may be modified and distributed under
|
||||
the terms of the GNU Public License. There is _NO_ warranty for this!
|
||||
|
||||
|
@ -24,55 +20,60 @@ Petr Michalek <petr.michalek@aca.cz>
|
|||
Jan Stocker
|
||||
Frank Sautter, levigo group
|
||||
Hans Petter Selasky
|
||||
Simon Peter <dn.tlp@gmx.net>
|
||||
Mario Goegel <m.goegel@gmx.de>
|
||||
|
||||
(...and all the others that have been forgotten...) :-)
|
||||
|
||||
No support for Asterisk 1.0.x any more, you need at least
|
||||
Asterisk 1.2.x , 1.4.x or 1.6.x.
|
||||
|
||||
Note:
|
||||
Eicon DIVA Server cards are now named Dialogic(R) Diva(R) Media Boards.
|
||||
|
||||
This chan_capi version includes:
|
||||
================================
|
||||
=====================================================
|
||||
- Multiple controller support
|
||||
- CID,DNID (callling party, called party)
|
||||
- CLIR/CLIP
|
||||
- Supplementary services, CD,HOLD,RETRIEVE,ECT
|
||||
- Supplementary services: CD (deflect/reroute),HOLD,RETRIEVE,ECT,3PTY
|
||||
- DTMF (dependend on card) + software DTMF support
|
||||
- Early B3 connects (always,success,never)
|
||||
- Digital audio (what did you think?)
|
||||
- Incoming/outgoing calls
|
||||
- Overlap sending (dialtone and additional digits)
|
||||
- E(xplicit) C(all) T(ransfer) (...although it's done implicit-but don't tell!)
|
||||
- Tuneable latency: you can configure the size of B3 blocks at compile time
|
||||
(in chan_capi.h, AST_CAPI_MAX_B3_BLOCK_SIZE)
|
||||
The default is 160 samples, for non-VoIP use you can tune it down to 130
|
||||
- Use asterisks internal DSP functions for DTMF
|
||||
- Alaw support
|
||||
- Ulaw support!
|
||||
- Eicon CAPI echo cancelation (echocancel=1)
|
||||
- a-Law support
|
||||
- u-Law support!
|
||||
- Dialogic(R) Diva(R) software DSP echo cancellation (echocancel=1)
|
||||
- Reject call waiting (ACO)
|
||||
- DID for Point to Point mode (a.k.a overlap receiving)
|
||||
- Rx/Tx gains (rxgain=1.0)
|
||||
- (Inter)national dialing prefix (for callerid) configurable in capi.conf
|
||||
- Rx/Tx gains using positive linar value (rxgain=1.0, txgain=1.0 means no change)
|
||||
- (Inter)national/subscriber dialing prefix (for callerid) configurable in capi.conf
|
||||
- CLI command "capi info" shows B channel status of chan_capi
|
||||
The called party can press # to drop the call
|
||||
- Catch all MSN (incomingmsn=*)
|
||||
- Some configuration enhancements (msn=123,124,125 and controller=1,2,3,4)
|
||||
- Some configuration enhancements (msn=123,124,125)
|
||||
- Added accountcode=
|
||||
- Echo squelching (echosquelch=1)
|
||||
- Callgroup support
|
||||
- report correct DIALSTATUS and HANGUPCAUSE.
|
||||
- Updated to support the new frame->delivery field
|
||||
- Compiles with different Asterisk versions (automatic build configuration)
|
||||
- receive faxes over CAPI (see below)
|
||||
- receive/send faxes for CAPI (see below)
|
||||
- Fixes and compatibility for BSD (Jan Stocker and Hans Petter Selasky)
|
||||
- Support 'type of number'.
|
||||
- ISDN hold.
|
||||
- CAPI Line Interconnect.
|
||||
- CAPI VoIP/RTP
|
||||
- CLI command "capi show channels" shows details on channel status.
|
||||
- Asterisk 1.4 jitterbuffer configuration.
|
||||
- some QSIG extensions (see README.qsig)
|
||||
- CCBS (call completion on busy subscriber)
|
||||
- CAPI CHAT (CAPI MeetMe using onboard DSPs)
|
||||
- KEYPAD digits detection
|
||||
- provide DATE/TIME in NT-mode.
|
||||
|
||||
Permissions
|
||||
===========
|
||||
|
||||
OpenPBX.org, by default, runs as the non-root user/group
|
||||
openpbx/openpbx. You must make sure that the /dev/capi* device files
|
||||
are readable by OpenPBX.org either by changing the ownership or the
|
||||
permissions of the the device files or by running OpenPBX.org as root.
|
||||
|
||||
The Dial string
|
||||
===============
|
||||
|
@ -85,18 +86,32 @@ The Dial string
|
|||
using '-'. The according interface is found by searching a match with
|
||||
the 'group' specified in the capi.conf for each interface.
|
||||
|
||||
The optional <callerid> followed by an ':' can be used to set a callerid
|
||||
for this dial() command, without changing the original channel's callerid.
|
||||
The optional <callerid> followed by an ':' can be used to set a caller ID
|
||||
for this dial() command, without changing the original channel's caller ID.
|
||||
|
||||
'params' is an optional part to set special settings for this call.
|
||||
The string consists of a list of characters with the following meaning:
|
||||
'b' : early B3 always.
|
||||
'B' : early B3 on successful calls only.
|
||||
'd' : use the default caller id which is set by defaultcid= in capi.conf
|
||||
't' : enable B3 only on in-band tones available indication as Q.931 (05/98)
|
||||
recommends (without this option it will be enabled on "PROGRESS" or
|
||||
"ALERTING" messages, any "Progress" indication or channel identification).
|
||||
'd' : use the default caller ID that is set by defaultcid= in capi.conf
|
||||
'o' : use overlap sending of number.
|
||||
(Useful if additional digits shall be send afterwards or together
|
||||
with 'b' to get dialtone and then send the number, e.g. if otherwise
|
||||
(Useful if additional digits should be send afterwards or together
|
||||
with 'b' to get the dialtone and then send the number, e.g., if
|
||||
no progress tones are available)
|
||||
'c' : do not send sending complete
|
||||
's' : activate 'stay-online': do not disconnect CAPI connection on hangup.
|
||||
This is needed to give additional commands like CCBS after hangup.
|
||||
To really hang up the CAPI connection, use either capicommand(hangup)
|
||||
or wait for chan_capi/network timeout (about 20 seconds).
|
||||
'G' : early Line-Interconnect / bridge: Use Line-Interconnect as soon as
|
||||
both B-channels are up. Both channels must be of type the CAPI and
|
||||
the incoming call may need 'capicommand(progress)' to enable Early B3
|
||||
on it as well as the dial option 'b' for the outgoing channel.
|
||||
Before Dial(), the capicommand(peerlink) must be used to signal the
|
||||
dialed channel its peer.
|
||||
|
||||
If the <interface-name> is used in dialstring, be sure the name (specified
|
||||
in capi.conf) does not start with 'contr' or 'g'.
|
||||
|
@ -107,56 +122,116 @@ The Dial string
|
|||
capi.conf has been removed. The callerID is also taken from the calling channel.
|
||||
|
||||
|
||||
CLI commands
|
||||
============
|
||||
|
||||
capi info:
|
||||
Show chan_capi version info.
|
||||
Show status of available B-channels.
|
||||
|
||||
capi debug:
|
||||
Enable CAPI message verbosity.
|
||||
|
||||
capi no debug:
|
||||
Disable CAPI message verbosity.
|
||||
|
||||
capi show channels:
|
||||
Display detailed information on CAPI B-channels.
|
||||
(Description see below)
|
||||
|
||||
capi chatinfo:
|
||||
Show status of CAPI CHAT.
|
||||
|
||||
capi ifcstate:
|
||||
Show state of interfaces. (Diva only, chan_capi
|
||||
compiled with 'make DIVA_STATUS=1')
|
||||
|
||||
capi show resources:
|
||||
Show resources in use.
|
||||
|
||||
capi exec:
|
||||
'capi exec CHANNEL command,parameter1,parameter2,....,parameterN'
|
||||
Exec capicommand 'command' for selected channel.
|
||||
|
||||
CAPI command application
|
||||
========================
|
||||
========================================
|
||||
chan_capi provides an additional Asterisk application
|
||||
capicommand()
|
||||
With this application, special capi commands and features can be used.
|
||||
With this application, special CAPI commands and features can be used.
|
||||
|
||||
Call Deflection:
|
||||
Forwards an unanswered call to another number.
|
||||
Example:
|
||||
exten => s,1,capicommand(deflect|12345678)
|
||||
exten => s,1,capicommand(deflect,12345678)
|
||||
|
||||
Fax receive:
|
||||
Receive a fax using CAPI.
|
||||
Receives a fax using CAPI.
|
||||
Example:
|
||||
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}|+49 6137 555123|Asterisk)
|
||||
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID},+49 6137 555123,Asterisk,kX)
|
||||
(more see below)
|
||||
|
||||
Fax send:
|
||||
Sends a fax using CAPI.
|
||||
Example:
|
||||
exten => s,1,capicommand(sendfax,/path/to/faxfile.sff,+49 6137 555123,Asterisk)
|
||||
(more see below)
|
||||
|
||||
Enable/Disable echosquelch:
|
||||
Enable or disable a very primitive echo suppressor.
|
||||
Disable this before you start recording voicemail or your files may get choppy.
|
||||
Enables or disable a very primitive echo suppressor.
|
||||
Disable this option before you start recording voicemail or your files may get choppy.
|
||||
Example:
|
||||
exten => s,1,capicommand(echosquelch|yes)
|
||||
exten => s,1,capicommand(echosquelch,yes)
|
||||
or
|
||||
exten => s,1,capicommand(echosquelch|no)
|
||||
exten => s,1,capicommand(echosquelch,no)
|
||||
|
||||
Enable/Disable echocancel:
|
||||
Enables or disables echo-cancel provided by CAPI driver/hardware.
|
||||
You might need to disable echo-cancel when the data/fax transmission is handled
|
||||
by a non-CAPI application. After hangup, this setting is restored to the value
|
||||
set in capi.conf.
|
||||
Example:
|
||||
exten => s,1,capicommand(echocancel,yes)
|
||||
or
|
||||
exten => s,1,capicommand(echocancel,no)
|
||||
|
||||
By default chan_capi deactivates echo-cancel for transit connections
|
||||
(Dial command called from existing call). You can use 'econtransitconn'
|
||||
configurations parameter (capi.conf) to change this behavior:
|
||||
econtransitconn=0 ; Deactivate EC on transit connections
|
||||
econtransitconn=1 ; Deactivate EC on secondary call of transit connection only
|
||||
econtransitconn=2 ; Deactivate EC on primary call of transit connection only
|
||||
econtransitconn=3 ; Do not deactivate EC on transit connections
|
||||
|
||||
Send Keypad Facility:
|
||||
Send Keypad Faciliaty information.
|
||||
Example:
|
||||
exten => s,1,capicommand(keypad,<digits>)
|
||||
|
||||
Malicious Call Identification:
|
||||
Report a call of malicious nature.
|
||||
Reports a call of malicious nature.
|
||||
Example:
|
||||
exten => s,1,capicommand(malicious)
|
||||
|
||||
Hold:
|
||||
Puts an answered call on hold, this has nothing to do with asterisk's onhold
|
||||
thingie (music et al).
|
||||
An optional parameter is the name of the variable which shall be set with
|
||||
Puts an answered call on hold, this has nothing to do with Asterisk's onhold
|
||||
(music et al).
|
||||
An optional parameter is the name of the variable, which should be set with
|
||||
the reference ID of the call on hold.
|
||||
Example:
|
||||
exten => s,1,capicommand(hold)
|
||||
or
|
||||
exten => s,1,capicommand(hold|MYHOLDVAR)
|
||||
exten => s,1,capicommand(hold,MYHOLDVAR)
|
||||
|
||||
Holdtype:
|
||||
Set the type of 'hold'. When Asterisk wants to put the call on hold, the specified method
|
||||
Sets the type of 'hold'. When Asterisk wants to put the call on hold, the specified method
|
||||
will be used.
|
||||
Example:
|
||||
exten => s,1,capicommand(holdtype|local) ;no hold, Asterisk can play MOH
|
||||
exten => s,1,capicommand(holdtype,local) ;no hold, Asterisk can play MOH
|
||||
or
|
||||
exten => s,1,capicommand(holdtype|hold) ;ISDN-HOLD
|
||||
exten => s,1,capicommand(holdtype,hold) ;ISDN-HOLD
|
||||
or
|
||||
; not yet implemented
|
||||
exten => s,1,capicommand(holdtype|notify) ;notify the peer only, Asterisk can play MOH
|
||||
exten => s,1,capicommand(holdtype,notify) ;notify the peer only, Asterisk can play MOH
|
||||
|
||||
|
||||
Retrieve:
|
||||
|
@ -165,12 +240,12 @@ Retrieve:
|
|||
Example:
|
||||
exten => s,1,capicommand(retrieve)
|
||||
or
|
||||
exten => s,1,capicommand(retrieve|${MYHOLDVAR})
|
||||
exten => s,1,capicommand(retrieve,${MYHOLDVAR})
|
||||
|
||||
ECT:
|
||||
Explicit call transfer of the call on hold (must put call on hold first!)
|
||||
Explicit Call Transfer of the call on hold (must put call on hold first!)
|
||||
Example:
|
||||
exten => s,1,capicommand(ect|${MYHOLDVAR})
|
||||
exten => s,1,capicommand(ect,${MYHOLDVAR})
|
||||
or
|
||||
[macro-capiect]
|
||||
exten => s,1,capicommand(ect)
|
||||
|
@ -178,7 +253,91 @@ ECT:
|
|||
exten => s,1,capicommand(hold)
|
||||
exten => s,2,Wait(1)
|
||||
exten => s,3,Dial(CAPI/contr1/1234,60,M(capiect))
|
||||
Note: Normaly a PBX needs 'implicit call transfer', which is done by default
|
||||
with this command. But if the line needs real 'explicit call transfer', use
|
||||
exten => s,1,capicommand(ect,x)
|
||||
instead.
|
||||
|
||||
3PTY:
|
||||
Initiates a Three-Party Conference (must have one call on hold and one active call!).
|
||||
Example:
|
||||
exten => s,1,capicommand(3pty_begin,${MYHOLDVAR})
|
||||
or
|
||||
[macro-capi3pty]
|
||||
exten => s,1,capicommand(3pty_begin)
|
||||
[default]
|
||||
exten => s,1,capicommand(hold)
|
||||
exten => s,2,Dial(CAPI/contr1/1234,,M(capi3pty))
|
||||
|
||||
Peer link creation:
|
||||
Creates a reference for chan_capi to know who is the calling channel on Dial().
|
||||
This is needed if you want to use CCBS/CCNR afterwards.
|
||||
Example:
|
||||
exten => s,1,capicommand(peerlink)
|
||||
|
||||
Hangup in mode 'stay-online':
|
||||
After hangup in 'stay-online' mode, the line is not really disconnected
|
||||
until timeout or command:
|
||||
exten => s,1,capicommand(hangup)
|
||||
This works after capicommand(peerlink) only.
|
||||
|
||||
Set local party to 'busy' or 'free':
|
||||
Sets the local phone to the status 'busy' or 'free' when
|
||||
awaiting a callback for CCBS/CCNR. If the network wants to
|
||||
call you back for CCBS/CCNR, chan_capi normaly does not know
|
||||
about the status of the extension who started the callback.
|
||||
By default, chan_capi assumes 'free', but you can change that
|
||||
with:
|
||||
exten => s,1,capicommand(ccpartybusy,${CCLINKAGEID},yes)
|
||||
or
|
||||
exten => s,1,capicommand(ccpartybusy,${CCLINKAGEID},no)
|
||||
|
||||
Call completion on subscriber busy (CCBS):
|
||||
To receive a callback when the dialed and busy party becomes free, aka
|
||||
call completion on subscriber busy, you can do the following:
|
||||
Example:
|
||||
exten => s,1,capicommand(peerlink) ;to let chan_capi know who is the calling channel.
|
||||
exten => s,2,Dial(CAPI/contr1/123456,60,g) ;'g' to go-on with the dialplan on busy.
|
||||
exten => s,3,NoOp(${CCLINKAGEID}) ;if this variable now contains a number, CCBS is possible.
|
||||
;here you can ask the caller if CCBS shall be activated...
|
||||
exten => s,4,capicommand(ccbs,${CCLINKAGEID},<context>,<exten>,<priority>)
|
||||
exten => s,5,NoOp(${CCBSSTATUS}) ;if CCBS was successfully enabled, it is set to "ACTIVATED".
|
||||
If the remote party becomes 'non-busy', the network initiates the callback that will be
|
||||
sent to the provided context/exten/priority. Of course, this only happens if your local
|
||||
phone is set to 'free' with capicommand(ccpartybusy), which is the default.
|
||||
In this context/exten/priority you should just setup a callfile to initiate an outgoing
|
||||
call from your extension to
|
||||
exten => s,1,Dial(CAPI/ccbs/${CCLINKAGEID}/)
|
||||
|
||||
Deactivate CCBS:
|
||||
To deactivate a previously activated CCBS, use the following command:
|
||||
Example:
|
||||
exten => s,1,capicommand(ccbsstop,${CCLINKAGEID})
|
||||
|
||||
Chat (MeetMe/Conference):
|
||||
See also README.media for details!
|
||||
If the CAPI card/driver supports it, the caller can be put into a chat-room:
|
||||
(This uses the DSPs onboard a Dialogic(R) Diva(R) Rev.2 Media Board.)
|
||||
exten => s,1,capicommand(chat,<roomname>,<options>,controller)
|
||||
Example:
|
||||
exten => s,1,capicommand(chat,salesmeeting,m,1,3-6)
|
||||
Possible options:
|
||||
'm' = The first caller will get music-on-hold until second caller arrives.
|
||||
'h<sec>' = Hangup after <sec> seconds if caller is alone in conference.
|
||||
'o' = The caller is operator
|
||||
'l' = The caller is listener
|
||||
|
||||
Progress / Early-B3 on incoming calls:
|
||||
Activate Early-B3 on incoming channels to signal progress tones
|
||||
when in NT-mode or if the Telco-line supports this.
|
||||
Example:
|
||||
exten => s,1,capicommand(progress)
|
||||
|
||||
Get CAPI application ID:
|
||||
To store the CAPI application ID in an Asterisk dialplan variable, use:
|
||||
Example:
|
||||
exten => s,1,capicommand(getid,CAPI_ID)
|
||||
exten => s,2,NoOp(CAPI appl-id is ${CAPI_ID})
|
||||
|
||||
Using CLIR
|
||||
==========
|
||||
|
@ -187,7 +346,7 @@ Use the SetCallerPres() application before you dial:
|
|||
exten => _X.,2,Dial(CAPI/contr1/${EXTEN})
|
||||
|
||||
|
||||
Enjoying early B3 connects (inband call progress, tones and announcements)
|
||||
Enjoying Early B3 connects (inband call progress, tones and announcements)
|
||||
==========================================================================
|
||||
Early B3 is configurable in the dialstring parameters.
|
||||
If you set a 'b', early B3 will always be used, also if the call fails,
|
||||
|
@ -195,7 +354,7 @@ because the number is unprovisioned, etc ...
|
|||
If you set a 'B', early B3 will only be used on successful calls,
|
||||
giving you ring indication,etc...
|
||||
|
||||
Don't use indications in the Dial command, your local exchange will do that for
|
||||
Do not use indications in the Dial command, your local exchange will do that for
|
||||
you:
|
||||
exten => _X.,1,Dial(CAPI/contr1/${EXTEN}/B,30)
|
||||
(early B3 on success)
|
||||
|
@ -214,17 +373,20 @@ you:
|
|||
(early B3 on success, fake indicatons if the exchange does not give us
|
||||
indications)
|
||||
|
||||
For normal PBX usage you would use the "b" option, always early B3.
|
||||
For normal PBX usage, you would use the "b" option, always Early B3.
|
||||
You can also add "t" option so B3 will be enabled only on in-band tones available
|
||||
indication as Q.931 (05/98) recommends.
|
||||
|
||||
Overlap sending (a.k.a. real dialtone)
|
||||
======================================
|
||||
When you dial an empty number, and have early B3 enabled, with:
|
||||
When you dial an empty number and have early B3 enabled, with:
|
||||
Dial(CAPI/g1//b)
|
||||
The channel will come up at once and give you the dialtone it gets from the
|
||||
the channel will come up at once and give you the dialtone it gets from the
|
||||
local exchange.
|
||||
At this point the channel is like a legacy phone, now you can send DTMF digits
|
||||
to dial.
|
||||
|
||||
|
||||
Example context for incoming calls on MSN 12345678:
|
||||
===================================================
|
||||
|
||||
|
@ -233,16 +395,29 @@ exten => 12345678,1,Dial(SIP/phone1)
|
|||
exten => 12345678,2,Hangup
|
||||
|
||||
|
||||
Short HOWTO of capicommand(receivefax|<filename>[|<stationid>|<headline>]):
|
||||
==========================================================================
|
||||
For those of you who have a CAPI card with an on-board DSP (like some Eicon and
|
||||
DIVA Server), this patch allows you to receive faxes.
|
||||
If you want to answer a channel in fax mode, use capicommand(receivefax|...)
|
||||
instead of Answer()
|
||||
If you use Answer(), you will be in voice mode. If the hardware DSP detects
|
||||
fax tone, you can switch from voice to fax mode by calling capicommand(receivefax|...).
|
||||
The parameter <filename> is mandatory and the parameters <stationid> and
|
||||
<headline> are optional.
|
||||
Short HOWTO of capicommand(receivefax...) and capicommand(sendfax...):
|
||||
========================================================================================
|
||||
For those of you who have a CAPI card with an on-board DSP (like Dialogic(R) Diva(R) Media Boards),
|
||||
this allows you to receive/send faxes.
|
||||
|
||||
capicommand(receivefax,<filename>[,<stationid>,<headline>,<options>]):
|
||||
-------------------------------------------------------------------------
|
||||
If you want to answer a channel in fax mode, use capicommand(receivefax,...)
|
||||
instead of Answer(). If you use Answer(), you will be in voice mode.
|
||||
If the hardware DSP detects fax tone, you can switch from voice to fax mode
|
||||
by calling capicommand(receivefax,...).
|
||||
The parameter <filename> is mandatory and the parameters <stationid>,
|
||||
<headline> and <options> are optional.
|
||||
By default, if fax reception was not successful, the file is deleted. If you want even
|
||||
partly received or broken fax files, use 'k' for "keep bad fax" in the <options>:
|
||||
capicommand(receivefax,/tmp/${UNIQUEID},+123456789,,k)
|
||||
You can activate extended fax support by 'X' in the <options>:
|
||||
capicommand(receivefax,/tmp/${UNIQUEID},+123456789,X)
|
||||
Please read details on extended fax options in README.Diva.fax.
|
||||
|
||||
To enable fax tone detection and redirect to extension 'fax', use config variable
|
||||
'faxdetect' in capi.conf. This can be limited to the first 'n' seconds of a connection
|
||||
using the setting 'faxdetecttime' in capi.conf.
|
||||
|
||||
Example of use :
|
||||
line number 123, play something, if a fax tone is detected, handle it
|
||||
|
@ -255,73 +430,172 @@ exten => 124,1,Goto(handle_fax,s,1)
|
|||
exten => fax,1,Goto(handle_fax,s,1)
|
||||
|
||||
[handle_fax]
|
||||
exten => s,1,capicommand(receivefax|/tmp/${UNIQUEID}[|<stationid>|<headline>])
|
||||
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
|
||||
exten => s,2,Hangup()
|
||||
exten => h,1,deadagi,fax.php // Run sfftobmp and mail it.
|
||||
|
||||
The output of capicommand(receivefax|...) is a SFF file.
|
||||
The output of capicommand(receivefax,...) is a SFF file.
|
||||
Use sfftobmp to convert it.
|
||||
With a DIVA Server, following features are provided:
|
||||
With a Dialogic(R) Diva(R) Media Board, the following features are provided:
|
||||
- fax up to 33600
|
||||
- high resolution
|
||||
- Color Fax
|
||||
- JPEG Compression is disabled (not tested yet)
|
||||
See README.Diva.fax for more details and description of all options.
|
||||
|
||||
capicommand(sendfax,<filename>[,<stationid>,<headline>,<options>]):
|
||||
------------------------------------------------------------
|
||||
To send a fax, you can use the same mechanism like with receivefax.
|
||||
Just replace the <filename> with the path to the .SFF file to send.
|
||||
You can activate extended fax support by 'X' in the <options>:
|
||||
capicommand(sendfax,/tmp/${UNIQUEID},+123456789,,X)
|
||||
Please read details on extended fax options in README.Diva.fax.
|
||||
|
||||
After disconnect of a fax connection, the following variables
|
||||
will be set for that channel:
|
||||
FAXSTATUS : 0 = OK, 1 = Error.
|
||||
FAXREASON : Value of B3 disconnect reason.
|
||||
FAXREASONTEXT : Decoded text of FAXREASON value.
|
||||
FAXRATE : The baud rate of the fax connection.
|
||||
FAXRESOLUTION : 0 = standard, 1 = high.
|
||||
FAXFORMAT : 0 = SFF.
|
||||
FAXPAGES : Number of pages received.
|
||||
FAXID : The ID of the remote fax maschine.
|
||||
|
||||
KEYPAD digits in NT-mode
|
||||
========================
|
||||
If the device connected to a NT-mode port sends KEYPAD digits
|
||||
instead of normal digits, this call is then send to extension
|
||||
'Kxxx'. Where 'xxx' stands for the KEYPAD digits sent.
|
||||
|
||||
CLI command "capi show channels"
|
||||
==============================================
|
||||
This CLI command shows detailed info on all CAPI channels.
|
||||
Column description:
|
||||
Line-Name : the name of the interface as defined in capi.conf
|
||||
NTmode : is the line in NT-mode instead fo TE-mode
|
||||
state : the state of the channel, like 'Conn', 'Disc', 'Dial', ...
|
||||
i/o : incoming or outgoing line
|
||||
bproto : protocol on CAPI ('fax', 'trans' or 'rtp')
|
||||
isdnstate : a string which may consists of the following characters
|
||||
* = PBX is active
|
||||
G = Line-Interconnect (CAPI bridge) active
|
||||
B = B-channel is up
|
||||
b = B-channel is requested
|
||||
P = Progress was signaled
|
||||
H = this line is on hold
|
||||
T = this line is in transfer (ECT) mode
|
||||
S = SETUP[_ACK] was signaled
|
||||
ton : type of number value
|
||||
number : the caller number and destination number
|
||||
|
||||
|
||||
Asterisk variables used/set by chan_capi
|
||||
========================================
|
||||
==========================================================
|
||||
|
||||
BCHANNELINFO
|
||||
On incomming call, this variable is set with the B-channel information value:
|
||||
On incomming calls, this variable is set with the B-channel information value:
|
||||
'0' : B-channel is used (default)
|
||||
'1' : D-channel is used (not implemented yet)
|
||||
'2' : neither B nor D channel is used (e.g. call waiting)
|
||||
'2' : neither B nor D-channel is used (e.g., call waiting)
|
||||
Call-Waiting: an incoming call with BCHANNELINFO not '0' cannot be accepted.
|
||||
Another connection must be dropped before accepting or use
|
||||
capicommand(deflect|<number>) to initiate call deflection to another destination.
|
||||
capicommand(deflect,<number>) to initiate call deflection to another destination.
|
||||
|
||||
CALLEDTON
|
||||
The 'type of number' value of the called number is saved in this variable on
|
||||
Incoming calls: 'type of number' value of the called number is saved in this variable on
|
||||
incomming call.
|
||||
Outgoing calls: Allows to specity the 'ETS 300 102-1' called party number octet 3
|
||||
(0x80 is used by default)
|
||||
|
||||
exten => _X.,1,Answer
|
||||
exten => _X.,n,Set(_CALLEDTON=${CALLEDTON}) ; Use value of incoming call for outgoing call
|
||||
exten => _X.,n,Dial(CAPI/ISDN3/100,10)
|
||||
|
||||
exten => _X.,1,Answer
|
||||
exten => _X.,n,Set(_CALLEDTON=1) ; Use new value
|
||||
exten => _X.,n,Dial(CAPI/ISDN3/100,10)
|
||||
|
||||
|
||||
CALLERTON
|
||||
The 'type of number' value to overwrite for the caller number on outgoing call.
|
||||
|
||||
_CALLERHOLDID
|
||||
If a call is put on hold (ISDN-HOLD), the reference id is saved in this variable.
|
||||
If a call is put on hold (ISDN-HOLD), the reference ID is saved in this variable.
|
||||
This variable is inherited as CALLERHOLDID to the dialed channel and will be used
|
||||
if e.g. capicommand(ect) is used to transfer the held call.
|
||||
if e.g., capicommand(ect) is used to transfer the held call.
|
||||
|
||||
CALLINGSUBADDRESS
|
||||
If set on dial(), the calling subaddress will be set to the content.
|
||||
|
||||
CALLEDSUBADDRESS
|
||||
If set on dial(), the called subaddress will be set to the content.
|
||||
|
||||
|
||||
CAPI_CIP
|
||||
The real CIP value, not the transformed 'transfercapability'.
|
||||
Set on incoming call automatically. If set on outgoing call, it is used
|
||||
instead of transfercapability.
|
||||
|
||||
CCBSSTATUS
|
||||
When using capicommand(ccbs,....), this variable is set to either "ERROR" or
|
||||
"ACTIVATED".
|
||||
|
||||
CCLINKAGEID
|
||||
If a Call-Linkage-Id is received for CCBS/CCNR, this variable contains this ID.
|
||||
But you need to use capicommand(peerlink) before dialing a CAPI channel, because
|
||||
of a design problem in Asterisk, chan_capi is not able to set channel variables
|
||||
of the calling channel.
|
||||
|
||||
CONNECTEDNUMBER
|
||||
Can be set before answering and if set, the content is used for
|
||||
IE 'Connected Number' on answering.
|
||||
|
||||
DISCONNECT_IND_REASON
|
||||
When CAPI reports DISCONNECT_IND, some CAPI reason codes are not set
|
||||
in HANGUPCAUSE, because they are not valid cause codes. To also
|
||||
get those CAPI reason codes, you can check this variable on hangup.
|
||||
This is e.g. useful for reason 0x3301, which tells that the ISDN
|
||||
connection is physically broken (cable).
|
||||
|
||||
FAXEXTEN
|
||||
If chan_capi sends the call to extensions 'fax', the original extension number
|
||||
If chan_capi sends the call to configured fax extension, the original extension number
|
||||
is saved in this variable.
|
||||
|
||||
PRI_CAUSE
|
||||
If set, this value will be used as hangup cause on hangup.
|
||||
|
||||
REDIRECTINGNUMBER
|
||||
On incoming call, if the call was redirected to you by someone, the
|
||||
On incoming calls, if the call was redirected to you by someone, the
|
||||
number of the redirecting party is saved in this variable.
|
||||
RDNIS is set as well.
|
||||
|
||||
REDIRECTREASON
|
||||
If the incoming call was redirected to you, this variable is set
|
||||
with the reason value.
|
||||
|
||||
|
||||
Functions (available with newer Asterisk only)
|
||||
==============================================
|
||||
REDIRECTIONNUMBER
|
||||
If an outgoing call is redirected, this variable may be set to the
|
||||
new destination.
|
||||
|
||||
VANITYNUMBER(<vanitynumber>)
|
||||
Converts the 'vanitynumber' into a digit-only string. International keypad is
|
||||
used, e.g. ABC=1, DEF=2, ...
|
||||
ISDNPI1 and ISDNPI2
|
||||
The two values of the information element PI (Progress Indicator).
|
||||
|
||||
Asterisk outgoing calls
|
||||
==========================================================
|
||||
|
||||
Distribution of outgoing calls is controlled by two
|
||||
configuration variables (capi.conf, controller specific).
|
||||
|
||||
hlimit - Number of reserved channels. If number of free
|
||||
channels is below the one specified by 'hlimit' value then
|
||||
no new outgoing calls are delivered to this controller.
|
||||
|
||||
slimit - If value is set for multiple belonging to same dialout group
|
||||
controllers then the outgoing calls are distributd as follows:
|
||||
Calls are delivered to the controller with smalest (in group)
|
||||
number and the amount of free channels bigger then or equal to
|
||||
one speciefied by 'slimit'. After amount of free channels for all
|
||||
included in the group controllers is decreased below one specified
|
||||
by 'slimit' value calls are distributed in rount robin fashion
|
||||
between all (in group) controllers.
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
+===================================================================+
|
||||
| HD Audio (Hight Definition Audio) |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Supported HD Audio vocoders |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Diva provides support for following HD Audio vocoders:
|
||||
|
||||
g722, ssiren7 siren14 and slin16
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Supported Diva Hardware |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
HD Audio support is provided by:
|
||||
Diva 4PRI PCI
|
||||
Diva 2PRI PCI
|
||||
Diva 4PRI PCIe HS
|
||||
Diva 2PRI PCIe HS
|
||||
Diva 1PRI PCIe HS
|
||||
Diva 8PRI PCIe FS 4LANE
|
||||
Diva 4PRI PCIe FS 4LANE
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| HD Audio over ISDN support |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
To activate support for HD Audio please allow all or one of HD Audio
|
||||
codecs for one or more CAPI controllers. You can do it by Diva WEB
|
||||
configuration or by edit of 'capi.conf'.
|
||||
|
||||
Diva hardware will use BC/HLC/LLC method to agree on HD Audio
|
||||
format with opposite side. In addition Diva hardware will
|
||||
perform analysis of B-channel data to determine if HD Audio
|
||||
format is signaled in band.
|
||||
|
||||
Dependent on this procedire Diva will use HD Audio format
|
||||
or change to G.711 if HD Audio is not supported by opposite side.
|
||||
|
||||
Diva hardware will always convert media to one requested by chan_capi format.
|
||||
Following conversions are performed automatically:
|
||||
|
||||
G.711 <-> HD Audio in case chan_capi uses HD Audio but opposite side not
|
||||
HD Audio <-> G.711/GSM/... in case opposite side uses HD Audio but
|
||||
chan_capi uses other codec
|
||||
|
||||
Examples of HD Audio operation:
|
||||
|
||||
G.722 <-> SLINEAR16
|
||||
G.722 <-> siren14
|
||||
G.722 <-> siren7
|
||||
G.722 <-> G.722
|
||||
|
||||
Using automatic convertion this is possible always use HD Audio on internel (IP) network and do not case
|
||||
about used on the line (ISDN) format.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| HD Audio support for IP conference endpoints |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
To activate HD Audio support for IP conferencing please add one or
|
||||
mode HD Audio codecs to codeclist of capi command 'resource'.
|
||||
Please read README.media for details on 'resource'
|
||||
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Conferencing between HD and NB Audio endpoints |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
In case of conference with HD and NB (Narrow Band) Audio endpoints
|
||||
the quelity of HD endpoints is preserved
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
+===================================================================+
|
||||
| Diva fax support |
|
||||
+-------------------------------------------------------------------+
|
||||
| |
|
||||
| Intelligent fax processing |
|
||||
| FoIP/VoIP (Fax/Voice over IP) T.38 fax support |
|
||||
| FoIP/VoIP clear channel fax support |
|
||||
| Color fax |
|
||||
| High resolution fax, non standard paper size |
|
||||
| Use of fax with chan_capi |
|
||||
| |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| INTELLIGENT FAX PROCESSING |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
The fax chan_capi command set provides an easy way to access fax-related functionality.
|
||||
|
||||
If you use fax document processing, you need to be aware of the following problems,
|
||||
that might occur:
|
||||
* It is necessary to maintain a constant data stream between the application and the fax device.
|
||||
Any interruption in this data stream will affect the quality of the fax document.
|
||||
* It is necessary to deal with various low-level T.30 protocol settings like scan line time,
|
||||
compression, error correction, etc.
|
||||
* Not every application or device supports the command-set features provided by T.30 fax protocol.
|
||||
This limits the functionality and may require modification of the existing application.
|
||||
* The usage of fax document compression forces you to deal with compressed data (reception),
|
||||
or to be able to generate compressed data stream on demand, or to provide documents in different
|
||||
compression formats (transmission).
|
||||
* The "classic" fax application is unable to deal with transmission speeds higher than 14400 bps.
|
||||
To be able use V.34 fax transmission speeds of up to 33600 bps, the application needs to be modified.
|
||||
|
||||
This section explains how the Dialogic(R) Diva(R) Media Board can overcome these drawbacks and
|
||||
allows you to use the chan_capi to process fax documents with a comparable level of reliability and
|
||||
flexibility as a sophisticated high-level fax API.
|
||||
|
||||
Reliable data transfer between application and Dialogic(R) Diva(R) Media Board
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Dialogic(R) Diva(R) Media Boards provide a high-performance block-oriented IDI (ISDN Direct Interface)
|
||||
between the board hardware and the host CPU. The data transfer is performed via a BUS master DMA.
|
||||
This enables a reliable data transfer between the host CPU and the Diva Media Board memory that is not
|
||||
affected by the host CPU load. At the same time, using the BUS master DMA reduces the host CPU load.
|
||||
The Dialogic(R) Diva(R) chan_capi/CAPI interface/drivers does not perform data processing. It is only
|
||||
used to forward the data stream between the application and the IDI interface.
|
||||
The entire data processing is performed on the RISC CPU of the Diva Media Board.
|
||||
The reliability of the data stream is ensured by the board hardware through buffering
|
||||
(up to 64 Kbytes for every channel) and block-oriented data transfer (blocks of up to 2 Kbytes)
|
||||
via the BUS master DMA.
|
||||
|
||||
Automatic T.30 protocol parameter adjustment
|
||||
--------------------------------------------
|
||||
|
||||
The chan_capi can ignore low-level T.30 protocol settings. The T.30 protocol stack that runs on the RISC CPU
|
||||
of the Dialogic(R) Diva(R) Media Board is able to perform the required adjustment of transmission parameters
|
||||
to provide reliable and fast document transmission without requiring application intervention.
|
||||
You can overrule the automatic T.30 protocol parameter adjustment with global fax
|
||||
configuration options in the Dialogic(R) Diva(R) WEB configuration interface.
|
||||
|
||||
ECM (Error Correction Mode) support
|
||||
-----------------------------------
|
||||
|
||||
You can control ECM support via global fax configuration options in the Dialogic(R) Diva(R) WEB configuration interface.
|
||||
If you use global Diva configuration options to enable ECM support, the Dialogic(R) Diva(R) Media Board will use
|
||||
ECM mode for document transfer, if supported by the opposite side.
|
||||
Diva Media Boards use their internal memory to store document data. They retrieve data for ECM re-transmissions
|
||||
from this internal buffer (up to 64 Kbytes for every channel). This reduces the host CPU load and increases
|
||||
the reliability of the fax transmission.
|
||||
|
||||
Document compression support
|
||||
----------------------------
|
||||
|
||||
Dialogic(R) Diva(R) Media Boards use MR, MMR, T.6 fax document compression. In order to reduce transmission time,
|
||||
Diva Media Boards select the best compression algorithm supported by the opposite side. The Diva Media Board's
|
||||
RISC CPU is used to re-compress 1D-coded page data from the application to the format requested by the opposite
|
||||
side (transmission) and to convert received data to 1D-coded page data that is sent to the application (reception).
|
||||
The re-compression process is handled internally by the board's RISC CPU and happens fully transparent to the
|
||||
application that deals only with 1D (MH) coded data.
|
||||
You can adjust the compression-related T.30 protocol settings via Global fax configuration options.
|
||||
|
||||
Automatic detection of document format
|
||||
--------------------------------------
|
||||
|
||||
chan_capi uses the context of the file to determine the format of the document and to apply
|
||||
all necessary for transmission of the document settings.
|
||||
Following media formats are detected:
|
||||
SFF, CFF (Color Fax in JPEG or T.43 format), text file
|
||||
|
||||
Diva supports media stream consisting from pages with different media types.
|
||||
|
||||
V.34 (33600 bps) fax support
|
||||
----------------------------
|
||||
|
||||
The V.34 fax support can be controlled via global fax configuration options in the Dialogic(R) Diva(R) Configuration
|
||||
web interface. If the Dialogic(R) Diva(R) Media Board is able to establish a connection with a transmission speed
|
||||
higher than 14400 bps (V.34), it handles this transparent to the application.
|
||||
|
||||
You can use the "divalogd" accounting utility that uses the Diva Media Board Management interface to get
|
||||
information on the transmission speed and the used compression algorithm.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| FoIP/VoIP (Fax/Voice over IP) T.38 FAX SUPPORT |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
You can use the Dialogic(R) Diva(R) softIP software to access T.38 functionality.
|
||||
|
||||
There is no need to change your chan_capi configuration. The Dialogic(R) Diva(R) softIP software exposes the
|
||||
CAPI interface towards chan_capi and the SIP interface towards the IP network.
|
||||
All T.38 and SIP-related configurations are handled using Diva WEB configuration interface.
|
||||
|
||||
This is no limitation of the voice and supplementary services functionality of chan_capi.
|
||||
You can change the call flow between voice and fax or invoke the supplementary services at the CAPI interface
|
||||
and the Diva softIP software handles all necessary media and SIP negotiation.
|
||||
|
||||
You can use the Diva hardware and the Diva softIP software in parallel on one system.
|
||||
It is possible to use line interconnect (conferencing) features between the Diva hardware and
|
||||
The Diva softIP software without any limitations.
|
||||
|
||||
You can use the Diva softIP software in virtual environments (VMWare, XEN, ...).
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| FoIP/VoIP CLEAR CHANNEL FAX SUPPORT |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Together with the Diva(R) Dialogic(R) hardware you can use the Dialogic(R) Diva(R) softIP software or chan_capi to
|
||||
access T.38 (only Diva softIP software) and Clear Channel Fax functionality.
|
||||
|
||||
If you use the Diva softIP software there is no need to change your chan_capi configuration.
|
||||
The Dialogic(R) Diva(R) softIP software exposes the CAPI interface towards chan_capi and the SIP interface towards
|
||||
the IP network. All T.38 and SIP related configurations are handled using the Diva WEB configuration interface.
|
||||
To activate Clear Channel Fax support, the Diva hardware should be switched in Resource Board mode.
|
||||
This is no limitation of the voice and supplementory services functionality of chan_capi.
|
||||
You can change the call flow between voice and fax or invoke the supplementary services at the CAPI interface
|
||||
and the Diva softIP software will handle all necessary media and SIP negotiation.
|
||||
You can use the Diva hardware in TDM (E.1/T.1/S0), in Resource Board mode and the Diva softIP software in
|
||||
parallel on one system. It is possible to use the line interconnect (conferencing) features between the Diva hardware and
|
||||
the Diva softIP software without any limitations.
|
||||
|
||||
If you use chan_capi, then you can use 'resource' command to assign DSP resources to connected
|
||||
by IP users. Resource PLCI allows to send and to receive fax documents over IP using
|
||||
Clear Channel fax and to use the DSP resources for processing of IP media and for conferencing.
|
||||
It is possible to use the line interconnect (conferencing) features between E.1/T.1/S0/PSTN and
|
||||
IP peers without any limitations.
|
||||
|
||||
Both the Diva softIP software and chan_capi allow to use G.729, G.723, iLBC, GSM, and other codecs
|
||||
supported by the Diva hardware.
|
||||
|
||||
You can use the Diva hardware, chan_capi, and Diva softIP software in virtual environments if access by software is supported (XEN).
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| COLOR FAX |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
The Dialogic (R) Diva(R) hardware and the Dialogic (R) Diva(R) softIP software support color fax and allow to send/receive
|
||||
fax document using
|
||||
Continuous tone color and gray-scale mode according to T.4 Annex E using JPEG coding
|
||||
Lossless color and gray-scale mode according to T.43 using JBIG coding
|
||||
|
||||
Color fax documents are processed using CFF.
|
||||
Each of these data formats starts with a unique pattern:
|
||||
0x53 0x66 - SFF - First bytes of magic number in SFF document header, CAPI 2.0 Annex B
|
||||
0xFF 0xD8 - T.4 - Annex E SOI marker
|
||||
0xFF 0xA8 0 T.43 - Start marker 0xFFA8
|
||||
|
||||
It is possible to change between different media types in the time of fax transmission. This
|
||||
allows to change media between black and white and color for every page.
|
||||
|
||||
After completion of transmission or reception of fax CFF (color/greyscale image format)
|
||||
variable FAXFORMAT is set to 8 (native format, CFF image) and variable FAXCFFFORMAT
|
||||
provides information about the image format.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| High resolution fax, non standard paper size |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
The Dialogic (R) Diva(R) hardware and the Dialogic (R) Diva(R) softIP software provide access to following T.30 features:
|
||||
Ultra/Super fine resolution
|
||||
Non standard paper formats
|
||||
|
||||
The current COMMON-ISDN-API specification defines paper formats ISO A4, ISO B4, and ISO A3
|
||||
at standard resolution (R8 x 3.85) and high resolution (R8 x 7.7).
|
||||
Support for B4 and A3 is optional.
|
||||
The Dialogic (R) Diva(R) software supports a COMMON-ISDN-API extension that enables FAX document transmission and
|
||||
reception with paper formats ISO A4, ISO B4, and ISO A3 and the following resolutions as specified in T.30:
|
||||
R8 x 3.85
|
||||
R8 x 7.7
|
||||
R8 x 15.4
|
||||
R16 x 15.4
|
||||
200 x 200 dpi
|
||||
300 x 300 dpi
|
||||
400 x 400 dpi
|
||||
300 x 600 dpi
|
||||
400 x 800 dpi
|
||||
600 x 1200 dpi
|
||||
600 x 600 dpi
|
||||
1200 x 1200 dpi
|
||||
|
||||
The page format and resolution information is passed via appropriate fields in the SFF page header.
|
||||
The Dialogic(R) Diva(R) SFF2TIFF utility provides conversion from SFF to TIFF format for all basic and
|
||||
extended resolutions and paper formats.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Use of fax with chan_capi |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Based on information from README
|
||||
|
||||
Reception of fax documents
|
||||
--------------------------
|
||||
|
||||
You can use the Dialogic (R) Diva(R) chan_capi configuration to activate fax support ("Fax detection" and "Fax detection time").
|
||||
The reception of the fax message is started using 'receivefax' capi command:
|
||||
|
||||
capicommand(receivefax,<filename>[,<stationid>,<headline>,<options>])
|
||||
|
||||
Parameters:
|
||||
'filename' - Contains the full path and file name for the resulting fax file, mandatory
|
||||
'stationid' - station ID, optional
|
||||
'headline' - head line, optional
|
||||
'options' - fax options, optional
|
||||
'X' - use fax T.30 extended (default)
|
||||
'x' - do not use fax T.30 extended
|
||||
'k' - keep fax document in case of errors (by default document is removed
|
||||
if fax transmission was not completed with success).
|
||||
'f' - allow Fine resolution (default)
|
||||
'F' - do not use Fine resolution
|
||||
'u' - activate support for Super/Ultra fine resolutions and paper formats
|
||||
'j' - enable JPEG coding
|
||||
'b' - enable T.43 coding
|
||||
't' - do not use T.85
|
||||
'e' - do not use ECM
|
||||
'm' - do not use MMR (T.6) coding
|
||||
'd' - do not use MR (2D) coding
|
||||
|
||||
It is possible to answer the incomming call using 'receivefax' command and start reception of
|
||||
the fax document directly.
|
||||
It is possible to answer a call using 'Answer' in voice mode and change to reception (transmission) of the fax by
|
||||
'receivefax' later, for example after the detection of the fax calling tone or after the user entered a password
|
||||
using DTMF digits.
|
||||
|
||||
Using resource ('resource' command) PLCI allows to receive fax documents over IP using Clear Channel fax.
|
||||
The 'resource' command allocates one resource PLCI for IP connections only and does not perform any actions for
|
||||
E.1/T.1/S0/PSTN connections. This allows for safe use of 'resource' command in any context.
|
||||
|
||||
Example:
|
||||
[isdn-in]
|
||||
exten => _X.,1,Answer() ; Answer in voice mode
|
||||
exten => _X.,n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
|
||||
exten => _X.,n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
|
||||
exten => _X.,n,BackGround(jpop) ; Play message and wait until detection of fax calling tone
|
||||
|
||||
exten => 124,1,Goto(handle_fax,s,1) ; Extension 124 is dedicated to fax, answer in fax mode
|
||||
|
||||
exten => fax,1,Goto(handle_fax,s,1) ; Fax calling tone detected, change to fax mode
|
||||
exten => i,1,Hangup() ; Received unexpected event
|
||||
|
||||
[handle_fax]
|
||||
exten => s,1,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
|
||||
exten => s,n,Hangup()
|
||||
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it
|
||||
|
||||
Example with Clear Channel fax support:
|
||||
|
||||
[handle_fax]
|
||||
exten => s,1,capicommand(resource,1-4) ; Assign resource PLCI (use controllers 1 to 4)
|
||||
exten => s,n,capicommand(receivefax,/tmp/${UNIQUEID}[,<stationid>,<headline>,<options>])
|
||||
exten => s,n,Hangup()
|
||||
exten => h,1,deadagi,fax.php ; Run sfftobmp and mail it
|
||||
|
||||
|
||||
Transmission of fax documents
|
||||
-----------------------------
|
||||
|
||||
The transmission of the fax message is started using 'sendfax' capi command:
|
||||
|
||||
capicommand(sendfax,<filename>[,<stationid>,<headline>,<options>])
|
||||
|
||||
Parameters:
|
||||
'filename' - Contains the full path and file name to be sent, mandatory
|
||||
sendfax command automatically detects the type of file
|
||||
using the context of file.
|
||||
Supported formats:
|
||||
.sff - SFF file
|
||||
.txt - text file
|
||||
.cff - JPEG/T.43 (color/gray tone) coded file
|
||||
'stationid' - station ID, optional
|
||||
'headline' - head line, optional
|
||||
'options' - fax options, optional
|
||||
'X' - use fax T.30 extended (default)
|
||||
'x' - do not use fax T.30 extended
|
||||
'f' - use Fine resolution
|
||||
'u' - activate support for Super/Ultra fine resolutions and paper formats
|
||||
't' - do not use T.85
|
||||
'e' - do not use ECM
|
||||
'm' - do not use MMR (T.6) coding
|
||||
'd' - do not use MR (2D) coding
|
||||
|
||||
You need to start the call using the 'Dial' command in voice mode and change to transmission (reception)
|
||||
of the fax by 'sendfax'. Optionally, you can wait until the user entered a password using DTMF digits.
|
||||
|
||||
Using resource ('resource' command) PLCI allows to transmit fax documents over IP using Clear Channel fax.
|
||||
The 'resource' command allocates one resource PLCI for IP connections only and does not perform any actions for
|
||||
E.1/T.1/S0/PSTN connections. This allows for safe use of 'resource' command in any context.
|
||||
|
||||
Example:
|
||||
|
||||
[dial_fax]
|
||||
exten => 1,1,Dial(capi/ISDN1/1234512345,20,G(handle_sendfax,s,1))
|
||||
|
||||
[handle_sendfax]
|
||||
exten => s,1,capicommand(sendfax,/tmp/sendfax001.sff,1234 1234 1234,Outgoing Fax)
|
||||
exten => s,n,deadagi,faxlog.php ; Log result and schedule restart if necessary
|
||||
exten => s,n,Hangup
|
||||
|
||||
|
||||
Example with Clear Channel fax support:
|
||||
|
||||
[handle_sendfax]
|
||||
exten => s,1,capicommand(resource,1-4) ; Assign resource PLCI
|
||||
exten => s,n,capicommand(sendfax,/tmp/sendfax001.sff,1234 1234 1234,Outgoing Fax)
|
||||
exten => s,n,deadagi,faxlog.php ; Log result and schedule restart if necessary
|
||||
exten => s,n,Hangup
|
||||
|
||||
Results of fax transmission
|
||||
---------------------------
|
||||
|
||||
After chan_capi completed the processing of the 'receivefax' or 'sendfax' commands, following variables are set:
|
||||
FAXSTATUS - Status of fax transmission
|
||||
0 - OK
|
||||
1 - Error
|
||||
FAXREASON - Value of B3 disconnect reason
|
||||
FAXREASONTEXT - Decoded text of FAXREASON value
|
||||
FAXRATE - The baud rate of the fax connection
|
||||
FAXRESOLUTION - Resolution of received fax message
|
||||
0 - standard
|
||||
1 - high
|
||||
FAXFORMAT - Format of received fax document
|
||||
0 - SFF (default, description in Annex B)
|
||||
1 - Plain fax format (modified Huffman coding)
|
||||
2 - PCX
|
||||
3 - DCX
|
||||
4 - TIFF
|
||||
5 - ASCII
|
||||
6 - Extended ANSI
|
||||
7 - Binary-File transfer
|
||||
8 - Native (CFF
|
||||
continuous-tone color and gray-scale T.4 Annex E using JPEG coding
|
||||
lossless color and gray-scale mode according to T.43)
|
||||
FAXCFFFORMAT - Valid if FAXFORMAT is set to 8 (native)
|
||||
1 - continuous tone color and gray-scale mode according to T.4 Annex E using JPEG coding
|
||||
2 - lossless color and gray-scale mode according to T.43 [7] using JBIG coding
|
||||
FAXPAGES - Number of pages received
|
||||
FAXID - The ID of the remote fax maschine
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
+===================================================================+
|
||||
| QSIG Abstraction |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| QSIG supplementary services |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
The QSIG network differentiates between four different types of call transfers,
|
||||
two unassisted and two assisted.
|
||||
The type of invoked unassisted call transfer depends on the call state.
|
||||
The type of assisted call transfers depends on the type of the switching
|
||||
equipment Dialogic(R) Diva(R) interfaces as well.
|
||||
The coding of the messages and the type of the transfer invoked, depends
|
||||
on the QSIG dialect and on the vendor-specific implementation of QSIG dialect.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Use Diva QSIG abstraction with chan_capi |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
To use Diva QSIG abstraction please add 'divaqsig=1' to configuration
|
||||
of CAPI controller (capi.conf).
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| QSIG abstraction |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Dialogic(R) Diva(R) System Release Software abstraction allows to write
|
||||
QSIG applications independent of the used QSIG dialect.
|
||||
|
||||
Name and Display information elements
|
||||
Name (Calling Pary Name, Called Party Name, Connected Party Name,
|
||||
Busy Party Name) and Display information elementss are converted to protocol
|
||||
independent format and delivered to (received from) application using
|
||||
Diva manufacturer extensions. Information elements encoded as facility array
|
||||
(for example in CONNECT_REQ) are converted in accordance with rules of active
|
||||
QSIG protocol.
|
||||
|
||||
Unassisted call transfer:
|
||||
The application can use CAPI call deflection. The Diva System Release software
|
||||
will automatically translate the call deflection request in the appropriate
|
||||
QSIG primitives. The translation depends on the Diva System Release software
|
||||
configuration and on the call state.
|
||||
You can invoke this feature in any call state, but the request may fail in
|
||||
case the used switching equipment does not support the required service.
|
||||
|
||||
Assisted call transfer:
|
||||
The application can use CAPI Explicit Call Transfer (ECT). The Diva System Release
|
||||
software will automatically translate ECT in the appropriate QSIG primitive.
|
||||
The translation depends on the Diva System Release configuration.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Conclusion |
|
||||
+-------------------------------------------------------------------+
|
||||
If reviewed in short form, you can use any ETSI application with QSIG and without
|
||||
the need to change any code to access QSIG call transfers. There is no need to deal
|
||||
with details of the underlying network.
|
||||
The same is true not only for QSIG but for all supported signaling protocols.
|
||||
The same interface can be used to access basic and supplementary services for
|
||||
ETSI, QSIG, SS7 ISUP, 5ESS, R2, RBS/CAS, ...
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| QSIG path replacement |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
There are three parties involved in the path replacement procedure;
|
||||
The party that initiated the call (party A), the party that initially received and
|
||||
transferred the call (party B) and the party that finally received the
|
||||
call after the call transfer (party C).
|
||||
|
||||
The goal of the call replacement procedure is to free switching equipment resources
|
||||
by the replacement of the chain A->B->C with chain A->C.
|
||||
To achieve this, party B will short cut the D-channel link between A and C and
|
||||
let A and C exchange D-channel messages. In most cases, party B will short
|
||||
cut the B-channel between A and C as well and preserve this connection until the path
|
||||
replacement is complete. If the path replacement will not proceed (not supported, ...),
|
||||
party B will preserve the D-channel and B-channel interconnections for the entire
|
||||
duration of the call.
|
||||
|
||||
After party B completes the call transfer procedure, one transfer complete message
|
||||
will be sent (Diva System Release softwre configuration option) and will invoke the path
|
||||
replacement procedure (Diva System Release configuration option). As part of this procedure,
|
||||
party A will prepare an alternative resource and send information about this resource over
|
||||
the D-channel to C through B.
|
||||
After the information about the alternative resource is received, C will establish a new call
|
||||
directly from C to A and replace A->B->C by C->A (A->B->C still running in parallel).
|
||||
After the new connection is established, A and C will establish a new B-channel connection
|
||||
and will exchange D-channel messages over B and release connections A->B and B->C.
|
||||
After the release is complete, C->A is preserved during the duration of the call.
|
||||
|
||||
The Diva System Release software supports all three parties A, B, and C in the above mentioned
|
||||
path replacement procedure.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Support at party A and C endpoints |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
The support at A and C endpoints is transparent to the applications.
|
||||
The Diva System Release software will replace one connection with another in
|
||||
a fully transparent way to the application.
|
||||
The data streaming between the application and the bearer resource will not be interrupted
|
||||
during this operation. Only one notification about the change of the B-channel and
|
||||
about the completion of the path replacement procedure is provided to the application but
|
||||
does not require any action from the application (in certain environments
|
||||
applications will use this notification to issue RESET_B3 REQ and restart the voice
|
||||
message if any. PBX applications do not need to perform any action).
|
||||
|
||||
Please note that party C responds to the call replacement procedure only if the change of the
|
||||
connection is supported by the underlying protocol. This change is not possible if the fax or
|
||||
modem session is already in progress. In this case, C will ignore the path replacement and
|
||||
the chain A->B->C will be preserved for the entire duration of the call.
|
||||
The same is true if the path replacement procedure fails for any reason.
|
||||
|
||||
The M-Board is required to provide the path replacement operation at A and B and it is
|
||||
responsible for moving the call between different connections transparently for application.
|
||||
The path replacement can be performed only between Dialogic(R) Diva(R) interfaces
|
||||
that belong to the same M-Board.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Support at the party B endpoint |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Party B is the party that uses ECT to perform the assisted QSIG call transfer.
|
||||
The type of call transfer and the messages sent after the call transfer is completed
|
||||
are specified by the Diva System Release software configuration. The software detects if
|
||||
compatible QSIG dialects are used for both parties of ECT and will automatically
|
||||
establish the D-channel bridge.
|
||||
The application is responsible to establish the B-channel bridge. The best practice is to
|
||||
establish the B-channel bridge (using CAPI line interconnect command) before issuing
|
||||
the CAPI ECT command. The Dialogic(R) Diva(R) CAPI will atomatically maintain the D-channel bridge.
|
||||
|
||||
If the M-Board is used at the party B endpoint, it is possible to activate "ECT Emulation".
|
||||
If active, the M-Board will automatically establish and maintain the B-channel and D-channel bridge
|
||||
once the ECT command is sent by the application. In this case, there is no need to maintain the B-channel
|
||||
bridge by the application. The M-Board will maintain all necessary resources until the path
|
||||
replacement procedure is completed or for the entire duration of the call.
|
||||
This option is available only for calls that belong to the same M-Board.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Call state of involved in the ECT calls |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
In case of QSIG, it is not necessary to put one of the calls, involved in the ECT, on hold.
|
||||
Moreover, it is possible to invoke the ECT if the consultation call is in alerted state
|
||||
(if supported by the switching equipment).
|
||||
To achieve this, independent from the state of the primary and of the consultation call operation
|
||||
of the ECT, it is necessary to set the CAPIECTPLCI variable to PLCI (getplci commang provides it in
|
||||
CAPIPLCI variable) of the primary call before invoking the ECT.
|
||||
|
||||
Example: The application accepts one call, creates the consultation call and once the alert is
|
||||
received, the consultation call starts the playback of message on the first call. After an
|
||||
additional command is received, the application proceeds with ECT, independent from the state
|
||||
of the consultation call.
|
||||
It is even possible to play the message to the first call until the path replacement is completed
|
||||
and parties A and C are connected directly.
|
||||
|
||||
ECT Example:
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
[macro-capiect]
|
||||
; Activate suppressor of ambient noise for consultation call
|
||||
exten => s,1,capicommand(noisesuppressor,yes)
|
||||
; Invoke ECT command
|
||||
exten => s,n,capicommand(ect)
|
||||
|
||||
[isdn-in]
|
||||
; Send progress message on incoming call
|
||||
exten => 12345,1,Progress()
|
||||
exten => 12345,n,Set(TIMEOUT(digit)=1) ; Set Digit Timeout to 5 seconds
|
||||
exten => 12345,n,Set(TIMEOUT(response)=5) ; Set Response Timeout to 10 seconds
|
||||
; Play message to incoming call using early media mode
|
||||
exten => 12345,n,Playback(demo-enterkeywords,noanswer,us)
|
||||
; Accept incoming call
|
||||
exten => 12345,n,Answer
|
||||
; Activate suppressor of ambient noises for incoming call
|
||||
exten => 12345,n,capicommand(noisesuppressor,yes)
|
||||
; Save PLCI of incoming call to CAPIPLCI variable
|
||||
exten => 12345,n,capicommand(getplci)
|
||||
; Set CAPIECTPLCI variable to PLCI of incoming call
|
||||
; and allow to export this variable to consultation call
|
||||
exten => 12345,n,Set(_CAPIECTPLCI=${CAPIPLCI})
|
||||
; Create consultation call and invoke ECT
|
||||
; ECT procedure will detect CAPIECTPLCI is set and use saved in this variable value
|
||||
; to identify the ECT party and invoke ECT independent from the state of the primary call
|
||||
exten => 12345,n,Dial(CAPI/ISDN1/100,10,M(capiect))
|
||||
exten => 12345,n,Hangup()
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
+===================================================================+
|
||||
| Diva streaming |
|
||||
+-------------------------------------------------------------------+
|
||||
| |
|
||||
| What is Diva streaming |
|
||||
| How to activate Diva streaming support in chan_capi |
|
||||
| Performance metrics on chan_capi |
|
||||
| Supported hardware |
|
||||
| |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| WHAT IS DIVA STREAMING |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Diva streaming is one extension to Diva IDI interface which provides:
|
||||
Reduction of host load
|
||||
Reduction of delay and delay variance of data stream
|
||||
|
||||
This achieved by:
|
||||
Use of individual and independent logical BUS master DMA channel
|
||||
for every data stream (for every PLCI)
|
||||
Data transfer without copy operations and without system calls/context switches
|
||||
Available for user mode and for kernel mode applications
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| HOW TO ACTIVATE DIVA STREAMING SUPPORT IN CHAN_CAPI |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
To activate Diva streaming support in chan_capi please compile
|
||||
chan_capi with MAKE variable DIVA_STREAMING set to one:
|
||||
|
||||
make DIVA_STREAMING=1
|
||||
|
||||
and install new chan_capi module:
|
||||
|
||||
make install DIVA_STREAMING=1
|
||||
|
||||
chan_capi automatically detects if Diva streaming is supported by available Diva hardware.
|
||||
|
||||
You can disable use of Diva streaming at run time (without need to re-compile of chan_capi)
|
||||
if you set "nodivastreaming" variable in "[general]" section of "capi.conf" to one:
|
||||
|
||||
[general]
|
||||
nodivastreaming=1
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| PERFORMANCE METRICS ON CHAN_CAPI |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Hardware: 8 x 2.8GHz Xeon, 8GByte memory, Debian lenny 64Bit
|
||||
Diva hardware: Dialogic Diva V-8PRI PCIe FS v1
|
||||
Test: 240 channels GSM voice streaming
|
||||
|
||||
Voice transcoding by Asterisk and data exchange using CAPI:
|
||||
System load 50%
|
||||
Voice delay (additional): 20 mSec, delay variance 10mSec
|
||||
|
||||
Voice transcoding by Astrisk and data exchange using Diva streaming:
|
||||
System load 10%
|
||||
Voice delay (additional): 2 mSec, delay variance 1 mSec
|
||||
|
||||
Voice transcoding by Diva and data exchange using Diva streaming:
|
||||
System load 2%
|
||||
Voice delay (additional): 2 mSec, delay variance 1 mSec
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| SUPPORTED HARDWARE |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Diva streaming is supported by following hardware:
|
||||
Dialogic Diva V-4PRI/E1/T1-120 PCI v1
|
||||
Dialogic Diva 4PRI/E1/T1-120 PCI v1
|
||||
Dialogic Diva V-2PRI/E1/T1-60 PCI v1
|
||||
Dialogic Diva 2PRI/E1/T1-60 PCI v1
|
||||
Dialogic Diva V-4PRI PCIe HS v1
|
||||
Dialogic Diva V-2PRI PCIe HS v1
|
||||
Dialogic Diva V-1PRI PCIe HS v1
|
||||
Dialogic Diva V-4PRI PCIe FS v1
|
||||
Dialogic Diva V-8PRI PCIe FS v1
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
+===================================================================+
|
||||
| AMI commands and events |
|
||||
| |
|
||||
| Device state events |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Action CapichatList |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
List all users in conference or in all conferences
|
||||
|
||||
Conference: Capi chat room name
|
||||
|
||||
If Conference is not provided then command lists all users in all capi chat rooms.
|
||||
|
||||
List of users is delicered as serie of CapichatList events.
|
||||
List of users starts ends with CapichatListComplete event.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Action CapichatMute |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Mute all regular users if conference or mute selected user.
|
||||
|
||||
Conference: Conference room to mute
|
||||
Member: User to mute (Channel name)
|
||||
Path: Path to mute (Rx or Tx)
|
||||
|
||||
If only Conference provided then entire room is muted.
|
||||
If only Member provided then only selected user is muted.
|
||||
If Path not provided then Tx path is assumed.
|
||||
Path is valid only if Member iss provided.
|
||||
|
||||
If mute only one member this command is alias for capicommand
|
||||
txdgain,-128
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Action CapichatUnmute |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Mute all regular users if conference or mute selected user.
|
||||
|
||||
Conference: Conference room to unmute
|
||||
Member: User to mute (Channel name)
|
||||
Path: Path to mute (Rx or Tx)
|
||||
|
||||
If only Conference provided then entire room is muted.
|
||||
If only Member provided then only selected user is muted.
|
||||
If Path not provided then Tx path is assumed.
|
||||
Path is valid only if Member iss provided.
|
||||
|
||||
If unmute only one member this command is alias for capicommand
|
||||
txdgain,0
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Action CapichatRemove |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Remove member from conference
|
||||
|
||||
Conference: Conference room name
|
||||
Member: User to remove (Channel name)
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Action CapiCommand |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Execute any of supported capicommand commands (echocance,
|
||||
noisesuppressor, ...).
|
||||
|
||||
Channel: Channel name
|
||||
Command: capicomand command
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Event CapichatList |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Provided information about state of conference member.
|
||||
|
||||
Event: CapichatList
|
||||
ActionID: Action ID as used in CapichatList request.
|
||||
Conference: Conference room name
|
||||
UserNumber: User in conference
|
||||
CallerIDNum: CID
|
||||
CallerIDName: CID name
|
||||
Channel: Channel name
|
||||
Admin: Yes/No
|
||||
Role: Listen onlys/Talk and listen/Talk only
|
||||
MarkedUser: Yes/No
|
||||
Muted: No/By self/By admin/
|
||||
Talking: Yes/No/Not monitored
|
||||
Domain: TDM/IP
|
||||
DTMF: %s\r\n"
|
||||
EchoCancel: Yes/No
|
||||
NoiseSupp: Yes/No
|
||||
RxAGC: Yes/No
|
||||
TxAGC: Yes/No
|
||||
RxGain: Gain value in dB
|
||||
TxGain: Gain value in dB
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Event CapichatListComplet |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Terminates serie of CapichatList events.
|
||||
|
||||
ListItems: Mumber of CapichatList events preceeding to this event
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Event CapichatJoin |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
User joined conference
|
||||
|
||||
Channel: User name (Channel name)
|
||||
Uniqueid: Unique channel ID
|
||||
Conference: Conference room name
|
||||
Conferencenum: Conference room number
|
||||
CallerIDnum: CID
|
||||
CallerIDname: CID name
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Event CapichatLeave |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
User leaved conference
|
||||
|
||||
Channel: User name (Channel name)
|
||||
Uniqueid: Unique channel ID
|
||||
Conference: Conference room name
|
||||
Conferencenum: Conference room number
|
||||
CallerIDnum: CID
|
||||
CallerIDname: CID name
|
||||
Duration: Time user spend in conference, sec.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Event CapichatEnd |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Last user leaved conference
|
||||
|
||||
Conference: Conference room name
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Device state event ISDN/I[N]/congestion |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Device state event ISDN/I[N]/congestion, where [N] is CAPI controller
|
||||
number.
|
||||
Provides state of CAPI interface.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Device state event capichat:[room] |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Device state event capichat:[room], where [room] is the conference
|
||||
name.
|
||||
Provides state of Capichat conference room.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,93 @@
|
|||
+===================================================================+
|
||||
| Message Waiting Indication (MWI) |
|
||||
+===================================================================+
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Control MWI indicators (MWI Server) |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Using Asterisk 1.6 or newer it is possible to provide information about state of user
|
||||
mailbox to ISDN phone.
|
||||
Dependent on the state of mailbox this is possible to send MWI Activate or MWI deactivate
|
||||
request to activate or to deactivate Message Waiting Indicator on the phone.
|
||||
|
||||
To activate MWI function on CAPI controller please provide in the configuration of this
|
||||
controller the list of mailboxes to be monitored:
|
||||
|
||||
mwimailbox=mailbox1[:controlling user number1[:controlling user provided number1]][@context1], ...
|
||||
|
||||
The use of parameters can differ from PBX to PBX and even from PBX installation to PBX installation.
|
||||
Following description apply to common use of parameters.
|
||||
|
||||
Where:
|
||||
mailbox - Number of mailbox. Used to subsscribe to mailbox (voicemail.conf
|
||||
and at same time used by PBX to address the MWI indicator on device.
|
||||
controlling user number - Number where mailbox can be accessed (often same as mailbox)
|
||||
controlling user provided number - Password, used by PBX to check permissions
|
||||
|
||||
Additional configuration parameters depends on type of PBX used and on the PBX installation:
|
||||
mwifacptynrtype - type of MWI facility party number, 0 - unknown (default), 1 - public
|
||||
mwifacptynrton - MWI facility party number type of number and numbering plan identification
|
||||
(coding as for byte 0 of the calling party number). This byte is only valid
|
||||
if byte mwifacptynrtype contains the value 1. Set to 0 by default.
|
||||
mwifacptynrpres - MWI facility party number type presentation and screening indicator
|
||||
(coding as for byte 1 of the calling party number). This byte is only valid
|
||||
if byte mwifacptynrtype contains the value 1. Setr to 0 by default.
|
||||
mwibasicservice - MWI basic Service, coded in accordance with ETS 300 196 [D.5]. Set to 1 (voice)
|
||||
by default.
|
||||
mwiinvocation - MWI invocation mode, 0 - deffered, 1 - immediate, 2 - combined,
|
||||
65535 - suppres invocation code. Set to 2 by default.
|
||||
|
||||
Example:
|
||||
|
||||
[ISDN1]
|
||||
controller=1
|
||||
mwimailbox=12345:12345:221122@other,12347:12348,12349
|
||||
|
||||
activates monitoring of the mailboxes: 12345@other, 12347@default and 12349@default and sending
|
||||
of MWI requests using CAPI controller 1.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Direct control MWI indicators (MWI Server) |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
This is possible to send MWI Activate and MWI deactivate messages
|
||||
directly from dialplan using capicommand(mwi, ...).
|
||||
This can be necessary if testing the system, if voice mailbox is managed
|
||||
by other software (not by asterisk) or to verify MWI parameters.
|
||||
|
||||
capicommand(mwi,xmit,activate, ...) where parameters are:
|
||||
CAPI controller, MWI basic service,Number Of Messages, Message Status, Message Reference, Invocation Mode,
|
||||
Facility Number Type, Type of Number, Presentation and Screening,Mailbox,
|
||||
Facility Number Type, Type of Number, Presentation and Screening, Controlling User Number,
|
||||
Facility Number Type, Type of Number, Presentaation and Screening, Controlling User Provided Number
|
||||
|
||||
capicommand(mwi,xmit,deactivate, ...) where parameters are:
|
||||
CAPI controller, MWI basic service, Invocation Mode,
|
||||
Facility Number Type, Type of Number, Presentation and Screening,Mailbox,
|
||||
Facility Number Type, Type of Number, Presentation and Screening, Controlling User Number
|
||||
|
||||
Example:
|
||||
exten => _X.,n,capicommand(mwi,xmit,activate,1|1|1|0|0|2|1|0|0|42|1|0|0|41||||)
|
||||
exten => _X.,n,capicommand(mwi,xmit,deactivate|1|1|2|1|0|0|41|1|0|0|41)
|
||||
|
||||
Please refer to COMMON-ISDN-API Version 2.0 Part III Supplementary Services for more details
|
||||
on parameters.
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Receive MWI messages (MWI Client) |
|
||||
+-------------------------------------------------------------------+
|
||||
|
||||
Upon reception of MWI Activate messages from network chan_capi automatically
|
||||
generates Asterisk MWI events for mailbox N@CAPI_Remote, where N is the
|
||||
received as part of MWI Activate message Calling Party Number.
|
||||
|
||||
|
||||
+-------------------------------------------------------------------+
|
||||
| Notes |
|
||||
+-------------------------------------------------------------------+
|
||||
PBX often use one separate BRI trunk for transferring of MWI information (only MWI requests are transmitted
|
||||
this trunk).
|
||||
|
||||
Certain PBX require up to 15 seconds until MWI information is processed.
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
chan_capi a Common ISDN API 2.0 implementation for Asterisk
|
||||
|
||||
QSIG Extension for chan_capi
|
||||
|
||||
Copyright (C) 2005-2007 Cytronics & Melware
|
||||
Armin Schindler <armin@melware.de>
|
||||
|
||||
Copyright (C) 2006-2007 Mario Goegel
|
||||
Mario Goegel <m.goegel@gmx.de>
|
||||
|
||||
This program is free software and may be modified and distributed under
|
||||
the terms of the GNU Public License. There is _NO_ warranty for this!
|
||||
|
||||
Thanks go to the debuggers, bugfixers, and contributors :)
|
||||
===========================================================================
|
||||
None yet - you will be welcome here :-)
|
||||
|
||||
(...and all the others that have been forgotten...) :-)
|
||||
|
||||
No support for Asterisk 1.0.x any more, you need at least
|
||||
Asterisk 1.2.x , 1.4.x or 1.6.x.
|
||||
|
||||
What is QSIG
|
||||
=============
|
||||
|
||||
QSIG is a protocol extension for ISDN.
|
||||
It is mainly used on connecting PBXs of different PBX vendors, which allows
|
||||
better interoperability.
|
||||
As example there can be a name of an extension transferred between different
|
||||
PBXs, which is not possibile with standard ISDN.
|
||||
|
||||
These extensions will be transmitted as encoded facility information elements.
|
||||
To use QSIG with Asterisk, you willll need a card such as a Dialogic(R) Diva(R)
|
||||
Media Board (BRI like PRI) that supports QSIG. Maybe others do also work, if so, let me now.
|
||||
|
||||
The QSIG support includes:
|
||||
==========================
|
||||
|
||||
- Name presentation on Call SETUP incoming like outgoing
|
||||
|
||||
- ISDN LEG INFO2 field - a message that delivers information about call diversions on incoming calls to Asterisk
|
||||
Data is stored in Asterisk variables:
|
||||
QSIG_LI2_DIVREASON Reason of divertion: 0 - unknown, 1 - unconditional, 2 - user busy, 3 - user no reply
|
||||
QSIG_LI2_ODIVREASON Reason of original divertion (like above)
|
||||
QSIG_LI2_DIVCOUNT divertion counter - how many divertions
|
||||
QSIG_LI2_DIVNUM diverting number
|
||||
QSIG_LI2_ODIVNUM original diverting number
|
||||
QSIG_LI2_DIVNAME diverting name
|
||||
QSIG_LI2_ODIVNAME original diverting name
|
||||
|
||||
at the moment only incoming handling is supported
|
||||
|
||||
- Possibility to inform QSIG switch about a call from the public network
|
||||
If you set the variable QSIG_SETUP=X, then the QSIG switch on the other side will know,
|
||||
that this call source is the public network - you will get a different ring tone, etc.
|
||||
In dialplan use: Set(__QSIG_SETUP=X) command.
|
||||
The leading "__" tells Asterisk, to export this variable to the outgoing channel and
|
||||
its subchannels
|
||||
|
||||
- Simple Call Transfer
|
||||
With capicommand(qsig_ct,src-id,dst-id), you can transfer an inbound call back to the qsig switch.
|
||||
The B-channel of this call will be relased, so that the line is free for a next call.
|
||||
Unfortunately, the call will be completely released by the switch if the target is busy.
|
||||
If you need to know whether your target is busy, you can use the call transfer feature below.
|
||||
|
||||
- Call Transfer (outgoing)
|
||||
You can do an outbound call transfer.
|
||||
First, you need the PLCI (logical channel ID) of your first channel. You can obtain it with capicommand(qsig_getplci). This
|
||||
command returns the channel ID in the variable QSIG_PLCI. Now, you can enable the call transfer feature.
|
||||
Simply add "Ct<PLCI>" to QSIG_SETUP (i.e., QSIG_SETUP="X/Ct${QSIG_PLCI}" ). On the next dial command the call will
|
||||
be automatically transferred. The transfer occurs after the CONNECT. If you want a transfer early on ringing, you
|
||||
may use "Ctr<PLCI>". Then the target user will get the information about the originating user, while his phone is ringing.
|
||||
|
||||
If the external switch offers an path replacement propose, it will be taken automatically in account.
|
||||
The B-channels will be cleared by the switch after the call is conneced. Your channels stay free.
|
||||
|
||||
- Automatic Call Transfer and Path Replacement (if allowed/possible) on bridge/line interconnect
|
||||
If a line interconnect is set up from Asterisk, chan_capi sends an Call Transfer facility out and waits for an
|
||||
Path Replacement Propose message - if no Path Replacement is received, the line interconnect will proceed.
|
||||
The Call Transfer allows your connected extensions in every case (if the switch supports the Call Transfer feature)
|
||||
to see the name and number of its connected peer.
|
||||
This should be configurable in the next release.
|
||||
|
||||
- decoding of incoming Call Transfer feature
|
||||
Enables inbound Path Replacement. If received, an automatic Path Replacement with Asterisk internal bridging will be fired.
|
||||
|
||||
- Support for sending CalledName
|
||||
If in the dialplan a variable CALLEDNAME was set, it will be sent out to the switch, while the Asterisk extension is ringing.
|
||||
|
||||
- Support for sending ConnectedName
|
||||
If in the dialplan a variable CONNECTEDNAME was set, it will be sent out to the switch AFTER connection is answered by asterisk
|
||||
|
||||
|
||||
Future Targets:
|
||||
===============
|
||||
- check code for buffer overflows
|
||||
- complete path replacement features
|
||||
- Call Rerouting feature [ECMA-174]
|
||||
- CCBS
|
||||
- AOC
|
||||
- sendtext implementation (e.g., display instructions on the connected set)
|
||||
- ...
|
||||
|
||||
How to use:
|
||||
===========
|
||||
|
||||
You will find more documentation at the chan_capi wiki.
|
||||
|
||||
Please visit: http://www.melware.org/ChanCapiConf
|
||||
|
||||
|
||||
|
||||
Simply enable QSIG with the following line in your capi.conf interface:
|
||||
|
||||
Here we go with new configuration
|
||||
|
||||
Set QSIG to one of the following values, which corresponds to your configuration.
|
||||
|
||||
0 QSIG turned off
|
||||
1 Alcatel (4400 & Enterprise - Maybe OXO/4200) ECMA (wrongly named ECMA - it is ETSI) variant
|
||||
2 Siemens HiPath 4000 ECMAV2 & Alcatel 4400/Enterprise in ISO mode
|
||||
|
||||
|
||||
ToDo List:
|
||||
==========
|
||||
|
||||
- Support for inbound rerouting
|
||||
- Enhance ASN1-97 Addressing Data Elements support - will save much code
|
||||
- Allow/Disallow Path Replacement within capi.conf - partially done
|
335
c20msg.c
335
c20msg.c
|
@ -1,335 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* decode capi 2.0 info word
|
||||
*/
|
||||
char *capi_info_string(unsigned int info)
|
||||
{
|
||||
switch (info) {
|
||||
/* informative values (corresponding message was processed) */
|
||||
case 0x0001:
|
||||
return "NCPI not supported by current protocol, NCPI ignored";
|
||||
case 0x0002:
|
||||
return "Flags not supported by current protocol, flags ignored";
|
||||
case 0x0003:
|
||||
return "Alert already sent by another application";
|
||||
|
||||
/* error information concerning CAPI_REGISTER */
|
||||
case 0x1001:
|
||||
return "Too many applications";
|
||||
case 0x1002:
|
||||
return "Logical block size to small, must be at least 128 Bytes";
|
||||
case 0x1003:
|
||||
return "Buffer exceeds 64 kByte";
|
||||
case 0x1004:
|
||||
return "Message buffer size too small, must be at least 1024 Bytes";
|
||||
case 0x1005:
|
||||
return "Max. number of logical connections not supported";
|
||||
case 0x1006:
|
||||
return "Reserved";
|
||||
case 0x1007:
|
||||
return "The message could not be accepted because of an internal busy condition";
|
||||
case 0x1008:
|
||||
return "OS resource error (no memory ?)";
|
||||
case 0x1009:
|
||||
return "CAPI not installed";
|
||||
case 0x100A:
|
||||
return "Controller does not support external equipment";
|
||||
case 0x100B:
|
||||
return "Controller does only support external equipment";
|
||||
|
||||
/* error information concerning message exchange functions */
|
||||
case 0x1101:
|
||||
return "Illegal application number";
|
||||
case 0x1102:
|
||||
return "Illegal command or subcommand or message length less than 12 bytes";
|
||||
case 0x1103:
|
||||
return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
|
||||
case 0x1104:
|
||||
return "Queue is empty";
|
||||
case 0x1105:
|
||||
return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
|
||||
case 0x1106:
|
||||
return "Unknown notification parameter";
|
||||
case 0x1107:
|
||||
return "The Message could not be accepted because of an internal busy condition";
|
||||
case 0x1108:
|
||||
return "OS Resource error (no memory ?)";
|
||||
case 0x1109:
|
||||
return "CAPI not installed";
|
||||
case 0x110A:
|
||||
return "Controller does not support external equipment";
|
||||
case 0x110B:
|
||||
return "Controller does only support external equipment";
|
||||
|
||||
/* error information concerning resource / coding problems */
|
||||
case 0x2001:
|
||||
return "Message not supported in current state";
|
||||
case 0x2002:
|
||||
return "Illegal Controller / PLCI / NCCI";
|
||||
case 0x2003:
|
||||
return "Out of PLCIs";
|
||||
case 0x2004:
|
||||
return "Out of NCCIs";
|
||||
case 0x2005:
|
||||
return "Out of LISTEN requests";
|
||||
case 0x2006:
|
||||
return "Out of FAX resources (protocol T.30)";
|
||||
case 0x2007:
|
||||
return "Illegal message parameter coding";
|
||||
|
||||
/* error information concerning requested services */
|
||||
case 0x3001:
|
||||
return "B1 protocol not supported";
|
||||
case 0x3002:
|
||||
return "B2 protocol not supported";
|
||||
case 0x3003:
|
||||
return "B3 protocol not supported";
|
||||
case 0x3004:
|
||||
return "B1 protocol parameter not supported";
|
||||
case 0x3005:
|
||||
return "B2 protocol parameter not supported";
|
||||
case 0x3006:
|
||||
return "B3 protocol parameter not supported";
|
||||
case 0x3007:
|
||||
return "B protocol combination not supported";
|
||||
case 0x3008:
|
||||
return "NCPI not supported";
|
||||
case 0x3009:
|
||||
return "CIP Value unknown";
|
||||
case 0x300A:
|
||||
return "Flags not supported (reserved bits)";
|
||||
case 0x300B:
|
||||
return "Facility not supported";
|
||||
case 0x300C:
|
||||
return "Data length not supported by current protocol";
|
||||
case 0x300D:
|
||||
return "Reset procedure not supported by current protocol";
|
||||
case 0x300E:
|
||||
return "TEI assignment failed or supplementary service not supported";
|
||||
case 0x3010:
|
||||
return "Request not allowed in this state";
|
||||
|
||||
/* informations about the clearing of a physical connection */
|
||||
case 0x3301:
|
||||
return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
|
||||
case 0x3302:
|
||||
return "Protocol error layer 2";
|
||||
case 0x3303:
|
||||
return "Protocol error layer 3";
|
||||
case 0x3304:
|
||||
return "Another application got that call";
|
||||
|
||||
/* T.30 specific reasons */
|
||||
case 0x3311:
|
||||
return "Connecting not successful (remote station is no FAX G3 machine)";
|
||||
case 0x3312:
|
||||
return "Connecting not successful (training error)";
|
||||
case 0x3313:
|
||||
return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
|
||||
case 0x3314:
|
||||
return "Disconnected during transfer (remote abort)";
|
||||
case 0x3315:
|
||||
return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
|
||||
case 0x3316:
|
||||
return "Disconnected during transfer (local tx data underrun)";
|
||||
case 0x3317:
|
||||
return "Disconnected during transfer (local rx data overflow)";
|
||||
case 0x3318:
|
||||
return "Disconnected during transfer (local abort)";
|
||||
case 0x3319:
|
||||
return "Illegal parameter coding (e.g. SFF coding error)";
|
||||
|
||||
/* disconnect causes from the network according to ETS 300 102-1/Q.931 */
|
||||
case 0x3481:
|
||||
return "Unallocated (unassigned) number";
|
||||
case 0x3482:
|
||||
return "No route to specified transit network";
|
||||
case 0x3483:
|
||||
return "No route to destination";
|
||||
case 0x3486:
|
||||
return "Channel unacceptable";
|
||||
case 0x3487:
|
||||
return "Call awarded and being delivered in an established channel";
|
||||
case 0x3490:
|
||||
return "Normal call clearing";
|
||||
case 0x3491:
|
||||
return "User busy";
|
||||
case 0x3492:
|
||||
return "No user responding";
|
||||
case 0x3493:
|
||||
return "No answer from user (user alerted)";
|
||||
case 0x3495:
|
||||
return "Call rejected";
|
||||
case 0x3496:
|
||||
return "Number changed";
|
||||
case 0x349A:
|
||||
return "Non-selected user clearing";
|
||||
case 0x349B:
|
||||
return "Destination out of order";
|
||||
case 0x349C:
|
||||
return "Invalid number format";
|
||||
case 0x349D:
|
||||
return "Facility rejected";
|
||||
case 0x349E:
|
||||
return "Response to STATUS ENQUIRY";
|
||||
case 0x349F:
|
||||
return "Normal, unspecified";
|
||||
case 0x34A2:
|
||||
return "No circuit / channel available";
|
||||
case 0x34A6:
|
||||
return "Network out of order";
|
||||
case 0x34A9:
|
||||
return "Temporary failure";
|
||||
case 0x34AA:
|
||||
return "Switching equipment congestion";
|
||||
case 0x34AB:
|
||||
return "Access information discarded";
|
||||
case 0x34AC:
|
||||
return "Requested circuit / channel not available";
|
||||
case 0x34AF:
|
||||
return "Resources unavailable, unspecified";
|
||||
case 0x34B1:
|
||||
return "Quality of service unavailable";
|
||||
case 0x34B2:
|
||||
return "Requested facility not subscribed";
|
||||
case 0x34B9:
|
||||
return "Bearer capability not authorized";
|
||||
case 0x34BA:
|
||||
return "Bearer capability not presently available";
|
||||
case 0x34BF:
|
||||
return "Service or option not available, unspecified";
|
||||
case 0x34C1:
|
||||
return "Bearer capability not implemented";
|
||||
case 0x34C2:
|
||||
return "Channel type not implemented";
|
||||
case 0x34C5:
|
||||
return "Requested facility not implemented";
|
||||
case 0x34C6:
|
||||
return "Only restricted digital information bearer capability is available";
|
||||
case 0x34CF:
|
||||
return "Service or option not implemented, unspecified";
|
||||
case 0x34D1:
|
||||
return "Invalid call reference value";
|
||||
case 0x34D2:
|
||||
return "Identified channel does not exist";
|
||||
case 0x34D3:
|
||||
return "A suspended call exists, but this call identity does not";
|
||||
case 0x34D4:
|
||||
return "Call identity in use";
|
||||
case 0x34D5:
|
||||
return "No call suspended";
|
||||
case 0x34D6:
|
||||
return "Call having the requested call identity has been cleared";
|
||||
case 0x34D8:
|
||||
return "Incompatible destination";
|
||||
case 0x34DB:
|
||||
return "Invalid transit network selection";
|
||||
case 0x34DF:
|
||||
return "Invalid message, unspecified";
|
||||
case 0x34E0:
|
||||
return "Mandatory information element is missing";
|
||||
case 0x34E1:
|
||||
return "Message type non-existent or not implemented";
|
||||
case 0x34E2:
|
||||
return "Message not compatible with call state or message type non-existent or not implemented";
|
||||
case 0x34E3:
|
||||
return "Information element non-existent or not implemented";
|
||||
case 0x34E4:
|
||||
return "Invalid information element contents";
|
||||
case 0x34E5:
|
||||
return "Message not compatible with call state";
|
||||
case 0x34E6:
|
||||
return "Recovery on timer expiry";
|
||||
case 0x34EF:
|
||||
return "Protocol error, unspecified";
|
||||
case 0x34FF:
|
||||
return "Interworking, unspecified";
|
||||
|
||||
/* B3 protocol 7 (Modem) */
|
||||
case 0x3500:
|
||||
return "Normal end of connection";
|
||||
case 0x3501:
|
||||
return "Carrier lost";
|
||||
case 0x3502:
|
||||
return "Error on negotiation, i.e. no modem with error correction at other end";
|
||||
case 0x3503:
|
||||
return "No answer to protocol request";
|
||||
case 0x3504:
|
||||
return "Remote modem only works in synchronous mode";
|
||||
case 0x3505:
|
||||
return "Framing fails";
|
||||
case 0x3506:
|
||||
return "Protocol negotiation fails";
|
||||
case 0x3507:
|
||||
return "Other modem sends wrong protocol request";
|
||||
case 0x3508:
|
||||
return "Sync information (data or flags) missing";
|
||||
case 0x3509:
|
||||
return "Normal end of connection from the other modem";
|
||||
case 0x350a:
|
||||
return "No answer from other modem";
|
||||
case 0x350b:
|
||||
return "Protocol error";
|
||||
case 0x350c:
|
||||
return "Error on compression";
|
||||
case 0x350d:
|
||||
return "No connect (timeout or wrong modulation)";
|
||||
case 0x350e:
|
||||
return "No protocol fall-back allowed";
|
||||
case 0x350f:
|
||||
return "No modem or fax at requested number";
|
||||
case 0x3510:
|
||||
return "Handshake error";
|
||||
|
||||
/* error info concerning the requested supplementary service */
|
||||
case 0x3600:
|
||||
return "Supplementary service not subscribed";
|
||||
case 0x3603:
|
||||
return "Supplementary service not available";
|
||||
case 0x3604:
|
||||
return "Supplementary service not implemented";
|
||||
case 0x3606:
|
||||
return "Invalid served user number";
|
||||
case 0x3607:
|
||||
return "Invalid call state";
|
||||
case 0x3608:
|
||||
return "Basic service not provided";
|
||||
case 0x3609:
|
||||
return "Supplementary service not requested for an incoming call";
|
||||
case 0x360a:
|
||||
return "Supplementary service interaction not allowed";
|
||||
case 0x360b:
|
||||
return "Resource unavailable";
|
||||
|
||||
/* error info concerning the context of a supplementary service request */
|
||||
case 0x3700:
|
||||
return "Duplicate invocation";
|
||||
case 0x3701:
|
||||
return "Unrecognized operation";
|
||||
case 0x3702:
|
||||
return "Mistyped argument";
|
||||
case 0x3703:
|
||||
return "Resource limitation";
|
||||
case 0x3704:
|
||||
return "Initiator releasing";
|
||||
case 0x3705:
|
||||
return "Unrecognized linked-ID";
|
||||
case 0x3706:
|
||||
return "Linked response unexpected";
|
||||
case 0x3707:
|
||||
return "Unexpected child operation";
|
||||
|
||||
/* Line Interconnect */
|
||||
case 0x3800:
|
||||
return "PLCI has no B-channel";
|
||||
case 0x3801:
|
||||
return "Lines not compatible";
|
||||
case 0x3802:
|
||||
return "PLCI(s) is (are) not in any or not in the same interconnection";
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
96
capi.conf
96
capi.conf
|
@ -6,47 +6,95 @@
|
|||
; general section
|
||||
|
||||
[general]
|
||||
nationalprefix=0
|
||||
internationalprefix=00
|
||||
rxgain=0.8
|
||||
txgain=0.8
|
||||
nationalprefix=0 ; or for example "+49"
|
||||
internationalprefix=00 ; or for example "+"
|
||||
;subscriberprefix=+4969 ; prefix including area code (some lines need this)
|
||||
rxgain=1.0 ;linear receive gain (1.0 = no change)
|
||||
txgain=1.0 ;linear transmit gain (1.0 = no change)
|
||||
language=de ;set default language
|
||||
;ulaw=yes ;set this, if you live in u-law world instead of a-law
|
||||
|
||||
;jb..... ;with Asterisk 1.4 you can configure jitterbuffer,
|
||||
;see Asterisk documentation for all jb* setting available.
|
||||
;mohinterpret=default ;Asterisk 1.4: default music on hold class when placed on hold.
|
||||
|
||||
|
||||
; interface sections ...
|
||||
|
||||
[ISDN1] ;this example interface gets name 'ISDN1' and may be any
|
||||
;name not starting with 'g' or 'contr'.
|
||||
;ntmode=yes ;if isdn card operates in nt mode, set this to yes
|
||||
;Use one interface section for each ISDN port!
|
||||
;ntmode=yes ;if the ISDN card operates in NT-mode, set this to 'yes'
|
||||
isdnmode=msn ;'MSN' (point-to-multipoint) or 'DID' (direct inward dial)
|
||||
;when using NT-mode, 'DID' should be set in any case
|
||||
incomingmsn=* ;allow incoming calls to this list of MSNs/DIDs, * = any
|
||||
;defaultcid=123 ;set a default caller id to that interface for dial-out,
|
||||
;this caller id will be used when dial option 'd' is set.
|
||||
;defaultcid=123 ;set a default caller ID to that interface for dial-out,
|
||||
;this caller ID will be used when the dial option 'd' is set.
|
||||
;controller=0 ;ISDN4BSD default
|
||||
;controller=7 ;ISDN4BSD USB default
|
||||
controller=1 ;capi controller number to use
|
||||
controller=1 ;CAPI controller number of this interface/port
|
||||
group=1 ;dialout group
|
||||
;prefix=0 ;set a prefix to calling number on incoming calls
|
||||
softdtmf=on ;enable/disable software dtmf detection, recommended for AVM cards
|
||||
relaxdtmf=on ;in addition to softdtmf, you can use relaxed dtmf detection
|
||||
accountcode= ;Asterisk accountcode to use in CDRs
|
||||
context=capi-in ;context for incoming calls
|
||||
holdtype=hold ;when Asterisk puts the call on hold, ISDN HOLD will be used. If
|
||||
;set to 'local' (default value), no hold is done and Asterisk may
|
||||
;prefix=0 ;set a prefix to the calling number on incoming calls
|
||||
softdtmf=on ;enable/disable software DTMF detection, recommended for AVM cards
|
||||
relaxdtmf=on ;in addition to softdtmf, you can use relaxed DTMF detection
|
||||
faxdetect=off ;enable faxdetection and redirection to EXTEN 'fax' for incoming and/or
|
||||
;outgoing calls. (default='off', possible values: 'incoming','outgoing','both')
|
||||
faxdetecttime=0 ;Only detect faxes during the first 'n' seconds of the call.
|
||||
;(default '0' meaning for the whole duration of the call)
|
||||
faxdestination=custom-fax,fax,1 ;Set custom context, exten and priority to jump to on faxdetect.
|
||||
;Default is "<current-context>,fax,1".
|
||||
accountcode= ;PBX accountcode to use in CDRs
|
||||
;amaflags=default;AMA flags for CDR ('default', 'omit', 'billing', or 'documentation')
|
||||
context=isdn-in ;context for incoming calls
|
||||
;holdtype=hold ;when the PBX puts the call on hold, ISDN HOLD will be used. If
|
||||
;set to 'local' (default value), no hold is done and the PBX may
|
||||
;play MOH.
|
||||
;immediate=yes ;DID: immediate start of pbx with extension 's' if no digits were
|
||||
;immediate=yes ;DID: immediate start of PBX with extension 's' if no digits were
|
||||
; received on incoming call (no destination number yet)
|
||||
;MSN: start pbx on CONNECT_IND and don't wait for SETUP/SENDING-COMPLETE.
|
||||
;MSN: start PBX on CONNECT_IND and do not wait for SETUP/SENDING-COMPLETE.
|
||||
; info like REDIRECTINGNUMBER may be lost, but this is necessary for
|
||||
; drivers/pbx/telco which does not send SETUP or SENDING-COMPLETE.
|
||||
;echosquelch=1 ;_VERY_PRIMITIVE_ echo suppression
|
||||
;echocancel=yes ;EICON DIVA SERVER (CAPI) echo cancelation
|
||||
;echosquelch=1 ;_VERY_PRIMITIVE_ echo suppression. Disable it before you start recording voicemail
|
||||
;or your files may get choppy. (you can use capicommand(echosquelch|no) for this)
|
||||
;echocancel=yes ;Dialogic(R) Diva(R) (CAPI) echo cancellation (yes=g165)
|
||||
;(possible values: 'no', 'yes', 'force', 'g164', 'g165')
|
||||
;echocancelpath=1;Dialogic(R) Diva(R) (CAPI) echo cancellation path
|
||||
;(possible values: default '1' - E.1/T.1/S0, '2' - IP, '3' - both)
|
||||
echocancelold=yes;use facility selector 6 instead of correct 8 (necessary for older eicon drivers)
|
||||
;echotail=64 ;echo cancel tail setting
|
||||
;echotail=64 ;echo cancel tail setting (default=0 for maximum)
|
||||
;echocancelnlp=1 ;activate non-linear-processing; this improves echo cancel ratio, but might
|
||||
;incorporate variable gain in the signal path.
|
||||
;bridge=yes ;native bridging (CAPI line interconnect) if available
|
||||
;callgroup=1 ;Asterisk call group
|
||||
devices=2 ;number of concurrent calls on this controller
|
||||
;(2 makes sense for single BRI, 30 for PRI)
|
||||
|
||||
;callgroup=1 ;PBX call group
|
||||
;pickupgroup=1 ;PBX pickup group (which call groups are we allowed to pickup)
|
||||
;transfergroup=1 ;Controller(s) where a transfer on native bridge is allowed to.
|
||||
;language=de ;set language for this device (overwrites default language)
|
||||
;disallow=all ;RTP codec selection (valid with Dialogic(R) Diva(R) Media Boards only)
|
||||
;allow=all ;RTP codec selection (valid with Dialogic(R) Diva(R) Media Boards only)
|
||||
devices=2 ;number of concurrent calls (B-Channels) on this controller
|
||||
;(2 makes sense for single BRI, 30/23 for PRI/T1)
|
||||
;jb..... ;with Asterisk 1.4 you can configure jitterbuffer,
|
||||
;see Asterisk documentation for all jb* setting available.
|
||||
;mohinterpret=default ;Asterisk 1.4: default music on hold class when placed on hold.
|
||||
;qsig=1 ;enable use of Q.SIG extensions. ECMA Variant
|
||||
;qsig_prnum=1234 ;enable inbound bridging - this should be an QSIG-network-wide unique number
|
||||
;divaqsig=on ;enable Diva QSIG and protocol independent implementation
|
||||
;mwifacptynrtype=0;type of MWI facility party number, 0 - unknown (default), 1 - public
|
||||
;mwifacptynrton=0 ;MWI facility party number type of number and numbering plan identification
|
||||
; (coding as for byte 0 of the calling party number).
|
||||
; This byte is only valid if byte mwifacptynrtype contains the value 1
|
||||
;mwifacptynrpres=0;MWI facility party number type presentation and screening indicator
|
||||
; (coding as for byte 1 of the calling party number).
|
||||
; This byte is only valid if byte mwifacptynrtype contains the value 1
|
||||
;mwibasicservice=1;MWI basic Service, coded in accordance with ETS 300 196 [D.5]
|
||||
;mwiinvocation=2 ;MWI invocation mode, 0 - deferred, 1 - immediate, 2 - combined,
|
||||
; 65535 - suppres invocation code
|
||||
;mwimailbox=12345 ;',' separated list of mailboxes for MWI in format:
|
||||
; mailbox[:controlling user number[:controlling user provided number]][@context]
|
||||
;hlimit=10 ;Do not use this controller for outgoing calls if less than 'hlimit' free channels is
|
||||
;left on this controller.
|
||||
;slimit=10 ;Try to use for outgoing calls other controller in group if less than 'slimit' free
|
||||
;channels is left on this controller. Always try to 'fill up' the controller with
|
||||
;smalest number in group. Create call if less than 'slimit' free channels left and
|
||||
;no other controller with respect to free channel count was found in group.
|
||||
|
||||
|
|
9725
chan_capi.c
9725
chan_capi.c
File diff suppressed because it is too large
Load Diff
666
chan_capi.h
666
chan_capi.h
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* (CAPI*)
|
||||
*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005 Cytronics & Melware
|
||||
* Copyright (C) 2005-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
|
@ -15,37 +13,76 @@
|
|||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_CAPI_H
|
||||
#define _ASTERISK_CAPI_H
|
||||
|
||||
#define CAPI_MAX_CONTROLLERS 16
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
#include <asterisk.h>
|
||||
#endif
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/features.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/cli.h>
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
#include <asterisk/rtp_engine.h>
|
||||
#else
|
||||
#include <asterisk/rtp.h>
|
||||
#endif
|
||||
#include <asterisk/causes.h>
|
||||
#include <asterisk/strings.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/devicestate.h>
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
#include "asterisk/abstract_jb.h"
|
||||
#endif
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
#include <asterisk/format_compatibility.h>
|
||||
#endif
|
||||
#include "asterisk/musiconhold.h"
|
||||
#include "dlist.h"
|
||||
#include "chan_capi_fmt.h"
|
||||
|
||||
#ifndef _PBX_CAPI_H
|
||||
#define _PBX_CAPI_H
|
||||
|
||||
#ifdef DIVA_STREAMING
|
||||
struct _diva_stream_scheduling_entry;
|
||||
#endif
|
||||
struct _pbx_capi_conference_bridge;
|
||||
|
||||
#define CAPI_MAX_CONTROLLERS 64
|
||||
#define CAPI_MAX_B3_BLOCKS 7
|
||||
|
||||
/* was : 130 bytes Alaw = 16.25 ms audio not suitable for VoIP */
|
||||
/* now : 160 bytes Alaw = 20 ms audio */
|
||||
/* now : 640 bytes slinear 16000Hz = 20 ms audio */
|
||||
/* you can tune this to your need. higher value == more latency */
|
||||
#define CAPI_MAX_B3_BLOCK_SIZE 160
|
||||
|
||||
#define CAPI_BCHANS 120
|
||||
#define ALL_SERVICES 0x1FFF03FF
|
||||
|
||||
#define CAPI_ISDNMODE_MSN 0
|
||||
#define CAPI_ISDNMODE_DID 1
|
||||
|
||||
/*
|
||||
* helper for ast_verbose with different verbose settings
|
||||
*/
|
||||
#define cc_verbose(o_v, c_d, text...) \
|
||||
do { \
|
||||
if ((o_v == 0) || (option_verbose > o_v)) { \
|
||||
if ((!c_d) || ((c_d) && (capidebug))) { \
|
||||
ast_mutex_lock(&verbose_lock); \
|
||||
ast_verbose(text); \
|
||||
ast_mutex_unlock(&verbose_lock); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
#define RTP_HEADER_SIZE 12
|
||||
|
||||
#define CAPI_MAX_FACILITYDATAARRAY_SIZE 300
|
||||
|
||||
#define COMMANDSEPARATOR "|,"
|
||||
|
||||
#ifdef CC_AST_HAS_FORMAT_T
|
||||
typedef format_t cc_format_t;
|
||||
#else
|
||||
typedef int cc_format_t;
|
||||
#endif
|
||||
|
||||
/* some helper functions */
|
||||
static inline void write_capi_word(void *m, unsigned short val)
|
||||
|
@ -53,11 +90,11 @@ static inline void write_capi_word(void *m, unsigned short val)
|
|||
((unsigned char *)m)[0] = val & 0xff;
|
||||
((unsigned char *)m)[1] = (val >> 8) & 0xff;
|
||||
}
|
||||
static inline unsigned short read_capi_word(void *m)
|
||||
static inline unsigned short read_capi_word(const void *m)
|
||||
{
|
||||
unsigned short val;
|
||||
|
||||
val = ((unsigned char *)m)[0] | (((unsigned char *)m)[1] << 8);
|
||||
val = ((const unsigned char *)m)[0] | (((const unsigned char *)m)[1] << 8);
|
||||
return (val);
|
||||
}
|
||||
static inline void write_capi_dword(void *m, unsigned int val)
|
||||
|
@ -67,45 +104,98 @@ static inline void write_capi_dword(void *m, unsigned int val)
|
|||
((unsigned char *)m)[2] = (val >> 16) & 0xff;
|
||||
((unsigned char *)m)[3] = (val >> 24) & 0xff;
|
||||
}
|
||||
static inline unsigned short read_capi_dword(void *m)
|
||||
static inline unsigned int read_capi_dword(const void *m)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
val = ((unsigned char *)m)[0] | (((unsigned char *)m)[1] << 8) |
|
||||
(((unsigned char *)m)[2] << 16) | (((unsigned char *)m)[3] << 24);
|
||||
val = ((const unsigned char *)m)[0] | (((const unsigned char *)m)[1] << 8) |
|
||||
(((const unsigned char *)m)[2] << 16) | (((const unsigned char *)m)[3] << 24);
|
||||
return (val);
|
||||
}
|
||||
|
||||
/*
|
||||
* definitions for compatibility with older versions of ast*
|
||||
* global name for messages and commands
|
||||
*/
|
||||
#ifdef CC_AST_HAVE_TECH_PVT
|
||||
#define CC_CHANNEL_PVT(c) c->tech_pvt
|
||||
#else
|
||||
#define CC_CHANNEL_PVT(c) c->pvt->pvt
|
||||
#endif
|
||||
#define CC_MESSAGE_NAME "capi"
|
||||
#define CC_MESSAGE_BIGNAME "CAPI"
|
||||
|
||||
#ifdef CC_AST_HAS_BRIDGED_CHANNEL
|
||||
#define CC_AST_BRIDGED_CHANNEL(x) ast_bridged_channel(x)
|
||||
#else
|
||||
#define CC_AST_BRIDGED_CHANNEL(x) x->bridge
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_BRIDGE_RESULT
|
||||
#define CC_BRIDGE_RETURN enum ast_bridge_result
|
||||
#else
|
||||
#define CC_BRIDGE_RETURN int
|
||||
#define AST_BRIDGE_COMPLETE 0
|
||||
#define AST_BRIDGE_FAILED -1
|
||||
#define AST_BRIDGE_FAILED_NOWARN -2
|
||||
#define AST_BRIDGE_RETRY -3
|
||||
#endif
|
||||
/*
|
||||
* define some private functions
|
||||
*/
|
||||
#define cc_mutex_t ast_mutex_t
|
||||
#define cc_mutex_init ast_mutex_init
|
||||
#define cc_mutex_lock(x) ast_mutex_lock(x)
|
||||
#define cc_mutex_unlock(x) ast_mutex_unlock(x)
|
||||
#define cc_mutex_destroy(x) ast_mutex_destroy(x)
|
||||
#define cc_log(x...) ast_log(x)
|
||||
#define cc_pbx_verbose(x...) ast_verbose(x)
|
||||
#define cc_copy_string(dst, src, size) ast_copy_string(dst, src, size)
|
||||
|
||||
#ifndef AST_MUTEX_DEFINE_STATIC
|
||||
#define AST_MUTEX_DEFINE_STATIC(mutex) \
|
||||
static ast_mutex_t mutex = AST_MUTEX_INITIALIZER
|
||||
static cc_mutex_t mutex = AST_MUTEX_INITIALIZER
|
||||
#endif
|
||||
|
||||
/*
|
||||
* definitions for nice compatibility
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_10_0
|
||||
#define CC_CHANNEL_PVT(c) ast_channel_tech_pvt(c)
|
||||
#else
|
||||
#define CC_CHANNEL_PVT(c) (c)->tech_pvt
|
||||
#endif /* CC_AST_HAS_VERSION_11_0 */
|
||||
#define CC_BRIDGE_RETURN enum ast_bridge_result
|
||||
|
||||
#ifdef CC_AST_HAS_UNION_DATA_IN_FRAME
|
||||
#define FRAME_DATA_PTR data.ptr
|
||||
#else
|
||||
#define FRAME_DATA_PTR data
|
||||
#endif
|
||||
|
||||
#if defined(CC_AST_HAS_UNION_SUBCLASS_IN_FRAME) || defined(CC_AST_HAS_VERSION_13_0)
|
||||
#define FRAME_SUBCLASS_INTEGER(x) x.integer
|
||||
|
||||
#ifndef CC_AST_HAS_VERSION_10_0
|
||||
#define SET_FRAME_SUBCLASS_CODEC(__a__,__b__) do {(__a__).codec = (__b__); }while(0)
|
||||
#define GET_FRAME_SUBCLASS_CODEC(__a__) (__a__).codec
|
||||
#elif !defined(CC_AST_HAS_VERSION_13_0)
|
||||
#define SET_FRAME_SUBCLASS_CODEC(__a__,__b__) do{ ast_format_from_old_bitfield(&(__a__).format, __b__); } while(0)
|
||||
#define GET_FRAME_SUBCLASS_CODEC(__a__) ast_format_to_old_bitfield(&(__a__).format)
|
||||
#else
|
||||
#define SET_FRAME_SUBCLASS_CODEC(__a__,__b__) do{ (__a__).format = ast_format_compatibility_bitfield2format(__b__); } while(0)
|
||||
#define GET_FRAME_SUBCLASS_CODEC(__a__) ast_format_compatibility_format2bitfield((__a__).format)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define FRAME_SUBCLASS_INTEGER(x) x
|
||||
#define SET_FRAME_SUBCLASS_CODEC(__a__, __b__) do { (__a__) = (__b__); }while(0)
|
||||
#define GET_FRAME_SUBCLASS_CODEC(__a__) __a__
|
||||
#endif
|
||||
|
||||
#ifndef CC_AST_HAS_CHANNEL_RELEASE
|
||||
#define ast_channel_release(x) ast_channel_free(x)
|
||||
#endif
|
||||
|
||||
#ifndef CC_AST_HAS_AST_DEVSTATE2STR
|
||||
#define ast_devstate2str(x) devstate2str(x)
|
||||
#endif
|
||||
|
||||
/* */
|
||||
#define return_on_no_interface(x) \
|
||||
if (!i) { \
|
||||
cc_verbose(4, 1, "CAPI: %s no interface for PLCI=%#x\n", x, PLCI); \
|
||||
return; \
|
||||
}
|
||||
|
||||
/*
|
||||
* B protocol settings
|
||||
*/
|
||||
#define CC_BPROTO_TRANSPARENT 0
|
||||
#define CC_BPROTO_FAXG3 1
|
||||
#define CC_BPROTO_RTP 2
|
||||
#define CC_BPROTO_VOCODER 3
|
||||
#define CC_BPROTO_FAX3_BASIC 4
|
||||
|
||||
/* FAX Resolutions */
|
||||
#define FAX_STANDARD_RESOLUTION 0
|
||||
#define FAX_HIGH_RESOLUTION 1
|
||||
|
@ -119,29 +209,63 @@ static inline unsigned short read_capi_dword(void *m)
|
|||
#define FAX_ASCII_FORMAT 5
|
||||
#define FAX_EXTENDED_ASCII_FORMAT 6
|
||||
#define FAX_BINARY_FILE_TRANSFER_FORMAT 7
|
||||
#define FAX_NATIVE_FILE_TRANSFER_FORMAT 8
|
||||
|
||||
/* Fax struct */
|
||||
typedef struct fax3proto3 {
|
||||
struct fax3proto3 {
|
||||
unsigned char len;
|
||||
unsigned short resolution __attribute__ ((packed));
|
||||
unsigned short format __attribute__ ((packed));
|
||||
unsigned char Infos[100] __attribute__ ((packed));
|
||||
} B3_PROTO_FAXG3;
|
||||
unsigned short resolution;
|
||||
unsigned short format;
|
||||
unsigned char Infos[100];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
typedef struct fax3proto3 B3_PROTO_FAXG3;
|
||||
|
||||
/* duration in ms for sending and detecting dtmfs */
|
||||
#define CAPI_DTMF_DURATION 0x40
|
||||
#define CAPI_DTMF_DURATION 0x50
|
||||
|
||||
#define CAPI_NATIONAL_PREF "0"
|
||||
#define CAPI_INTERNAT_PREF "00"
|
||||
#define CAPI_SUBSCRIBER_PREF ""
|
||||
|
||||
#define ECHO_TX_COUNT 5 /* 5 x 20ms = 100ms */
|
||||
#define ECHO_EFFECTIVE_TX_COUNT 3 /* 2 x 20ms = 40ms == 40-100ms ... ignore first 40ms */
|
||||
#define ECHO_TXRX_RATIO 2.3 /* if( rx < (txavg/ECHO_TXRX_RATIO) ) rx=0; */
|
||||
|
||||
#define FACILITYSELECTOR_DTMF 1
|
||||
#define FACILITYSELECTOR_SUPPLEMENTARY 3
|
||||
#define FACILITYSELECTOR_LINE_INTERCONNECT 5
|
||||
#define FACILITYSELECTOR_ECHO_CANCEL 8
|
||||
#define FACILITYSELECTOR_DTMF 0x0001
|
||||
#define FACILITYSELECTOR_SUPPLEMENTARY 0x0003
|
||||
#define FACILITYSELECTOR_LINE_INTERCONNECT 0x0005
|
||||
#define FACILITYSELECTOR_ECHO_CANCEL 0x0008
|
||||
#define PRIV_SELECTOR_DTMF_ONDATA 0x00fa
|
||||
#define FACILITYSELECTOR_FAX_OVER_IP 0x00fd
|
||||
#define FACILITYSELECTOR_VOICE_OVER_IP 0x00fe
|
||||
|
||||
#define EC_FUNCTION_ENABLE 1
|
||||
#define EC_FUNCTION_DISABLE 2
|
||||
#define EC_FUNCTION_FREEZE 3
|
||||
#define EC_FUNCTION_RESUME 4
|
||||
#define EC_FUNCTION_RESET 5
|
||||
#define EC_OPTION_DISABLE_NEVER 0
|
||||
#define EC_OPTION_DISABLE_G165 (1<<2)
|
||||
#define EC_OPTION_DISABLE_G164_OR_G165 (1<<1 | 1<<2)
|
||||
#define EC_DEFAULT_TAIL 0 /* maximum */
|
||||
|
||||
/*
|
||||
EC path mask
|
||||
*/
|
||||
#define EC_ECHOCANCEL_PATH_IFC 1 /* Default, activate EC for E.1/T.1/S0 only */
|
||||
#define EC_ECHOCANCEL_PATH_IP 2 /* Activate EC for IP */
|
||||
#define EC_ECHOCANCEL_PATH_BITS (EC_ECHOCANCEL_PATH_IFC | EC_ECHOCANCEL_PATH_IP)
|
||||
|
||||
/*
|
||||
Control EC on transit connectionss
|
||||
*/
|
||||
#define EC_ECHOCANCEL_TRANSIT_OFF 0 /* EC deactivated on transit connection, default */
|
||||
#define EC_ECHOCANCEL_TRANSIT_A 1 /* EC activated on side A of transsit connection */
|
||||
#define EC_ECHOCANCEL_TRANSIT_B 2 /* EC activated on side B of transsit connection */
|
||||
#define EC_ECHOCANCEL_TRANSIT_AB (EC_ECHOCANCEL_TRANSIT_A | EC_ECHOCANCEL_TRANSIT_B)
|
||||
#define EC_ECHOCANCEL_TRANSIT_BITS (EC_ECHOCANCEL_TRANSIT_A | EC_ECHOCANCEL_TRANSIT_B)
|
||||
|
||||
|
||||
#define CC_HOLDTYPE_LOCAL 0
|
||||
#define CC_HOLDTYPE_HOLD 1
|
||||
|
@ -149,23 +273,22 @@ typedef struct fax3proto3 {
|
|||
|
||||
/*
|
||||
* state combination for a normal incoming call:
|
||||
* DIS -> ALERT -> CON -> BCON -> CON -> DIS
|
||||
* DIS -> ALERT -> CON -> DIS
|
||||
*
|
||||
* outgoing call:
|
||||
* DIS -> CONP -> BCONNECTED -> CON -> DIS
|
||||
* DIS -> CONP -> CON -> DIS
|
||||
*/
|
||||
|
||||
#define CAPI_STATE_ALERTING 1
|
||||
#define CAPI_STATE_CONNECTED 2
|
||||
#define CAPI_STATE_BCONNECTED 3
|
||||
|
||||
#define CAPI_STATE_DISCONNECTING 4
|
||||
#define CAPI_STATE_DISCONNECTED 5
|
||||
#define CAPI_STATE_DISCONNECTING 3
|
||||
#define CAPI_STATE_DISCONNECTED 4
|
||||
|
||||
#define CAPI_STATE_CONNECTPENDING 6
|
||||
#define CAPI_STATE_ANSWERING 7
|
||||
#define CAPI_STATE_DID 8
|
||||
#define CAPI_STATE_INCALL 9
|
||||
#define CAPI_STATE_CONNECTPENDING 5
|
||||
#define CAPI_STATE_ANSWERING 6
|
||||
#define CAPI_STATE_DID 7
|
||||
#define CAPI_STATE_INCALL 8
|
||||
|
||||
#define CAPI_STATE_ONHOLD 10
|
||||
|
||||
|
@ -175,36 +298,114 @@ typedef struct fax3proto3 {
|
|||
|
||||
#define CAPI_MAX_STRING 2048
|
||||
|
||||
#define CAPI_FAX_DETECT_INCOMING 0x00000001
|
||||
#define CAPI_FAX_DETECT_OUTGOING 0x00000002
|
||||
#define CAPI_FAX_STATE_HANDLED 0x00010000
|
||||
#define CAPI_FAX_STATE_ACTIVE 0x00020000
|
||||
#define CAPI_FAX_STATE_ERROR 0x00040000
|
||||
#define CAPI_FAX_STATE_SENDMODE 0x00080000
|
||||
#define CAPI_FAX_STATE_CONN 0x00100000
|
||||
#define CAPI_FAX_STATE_MASK 0xffff0000
|
||||
|
||||
struct cc_capi_gains {
|
||||
unsigned char txgains[256];
|
||||
unsigned char rxgains[256];
|
||||
};
|
||||
|
||||
#define CAPI_ISDN_STATE_SETUP 0x0001
|
||||
#define CAPI_ISDN_STATE_SETUP_ACK 0x0002
|
||||
#define CAPI_ISDN_STATE_HOLD 0x0004
|
||||
#define CAPI_ISDN_STATE_ECT 0x0008
|
||||
#define CAPI_ISDN_STATE_PROGRESS 0x0010
|
||||
#define CAPI_ISDN_STATE_LI 0x0020
|
||||
#define CAPI_ISDN_STATE_DISCONNECT 0x0040
|
||||
#define CAPI_ISDN_STATE_DID 0x0080
|
||||
#define CAPI_ISDN_STATE_PBX 0x8000
|
||||
#define CAPI_ISDN_STATE_SETUP 0x00000001
|
||||
#define CAPI_ISDN_STATE_SETUP_ACK 0x00000002
|
||||
#define CAPI_ISDN_STATE_HOLD 0x00000004
|
||||
#define CAPI_ISDN_STATE_ECT 0x00000008
|
||||
#define CAPI_ISDN_STATE_PROGRESS 0x00000010
|
||||
#define CAPI_ISDN_STATE_LI 0x00000020
|
||||
#define CAPI_ISDN_STATE_DISCONNECT 0x00000040
|
||||
#define CAPI_ISDN_STATE_DID 0x00000080
|
||||
#define CAPI_ISDN_STATE_B3_PEND 0x00000100
|
||||
#define CAPI_ISDN_STATE_B3_UP 0x00000200
|
||||
#define CAPI_ISDN_STATE_B3_CHANGE 0x00000400
|
||||
#define CAPI_ISDN_STATE_RTP 0x00000800
|
||||
#define CAPI_ISDN_STATE_HANGUP 0x00001000
|
||||
#define CAPI_ISDN_STATE_EC 0x00002000
|
||||
#define CAPI_ISDN_STATE_DTMF 0x00004000
|
||||
#define CAPI_ISDN_STATE_B3_SELECT 0x00008000
|
||||
#define CAPI_ISDN_STATE_ISDNPROGRESS 0x00010000
|
||||
#define CAPI_ISDN_STATE_3PTY 0x10000000
|
||||
#define CAPI_ISDN_STATE_PBX_DONT 0x40000000
|
||||
#define CAPI_ISDN_STATE_PBX 0x80000000
|
||||
|
||||
#define CAPI_ISDN_STATE2_PROCEEDING 0x00000001
|
||||
#define CAPI_ISDN_STATE2_PROCEEDING_PENDING 0x00000002
|
||||
|
||||
#define CAPI_CHANNELTYPE_B 0
|
||||
#define CAPI_CHANNELTYPE_D 1
|
||||
#define CAPI_CHANNELTYPE_NULL 2
|
||||
|
||||
#define CAPI_RESOURCE_PLCI_NULL 0
|
||||
#define CAPI_RESOURCE_PLCI_DATA 1
|
||||
#define CAPI_RESOURCE_PLCI_LINE 2
|
||||
|
||||
/* the lower word is reserved for capi commands */
|
||||
#define CAPI_WAITEVENT_B3_UP 0x00010000
|
||||
#define CAPI_WAITEVENT_B3_DOWN 0x00020000
|
||||
#define CAPI_WAITEVENT_ANSWER_FINISH 0x00030000
|
||||
#define CAPI_WAITEVENT_HOLD_IND 0x00040000
|
||||
#define CAPI_WAITEVENT_ECT_IND 0x00050000
|
||||
|
||||
/* Features and settings of current connection */
|
||||
#define CAPI_FSETTING_STAYONLINE 0x00000001
|
||||
#define CAPI_FSETTING_EARLY_BRIDGE 0x00000002
|
||||
#define CAPI_FSETTING_EARLYB3_ONLY_WHEN_TONES_AVAIL 0x00000004
|
||||
|
||||
/* Private qsig data for capi device */
|
||||
struct cc_qsig_data {
|
||||
int calltransfer_active;
|
||||
int calltransfer;
|
||||
int calltransfer_onring;
|
||||
unsigned int callmark;
|
||||
|
||||
char *dnameid;
|
||||
|
||||
/* Path Replacement */
|
||||
int pr_propose_sendback; /* send back an prior received PR PROPOSE on Connect */
|
||||
int pr_propose_sentback; /* set to 1 after sending an PR PROPOSE */
|
||||
int pr_propose_active;
|
||||
int pr_propose_doinboundbridge; /* We have to to bridge a call back to asterisk */
|
||||
char *pr_propose_cid; /* Call identity */
|
||||
char *pr_propose_pn; /* Party Number */
|
||||
|
||||
char if_pr_propose_pn[AST_MAX_EXTENSION]; /* configured interface Party Number */
|
||||
|
||||
/* Partner Channel - needed for many features */
|
||||
struct capi_pvt *partner_ch;
|
||||
unsigned int partner_plci;
|
||||
ast_cond_t event_trigger;
|
||||
unsigned int waitevent;
|
||||
};
|
||||
|
||||
/* ! Private data for a capi device */
|
||||
struct capi_pvt {
|
||||
ast_mutex_t lock;
|
||||
int fd;
|
||||
int fd2;
|
||||
cc_mutex_t lock;
|
||||
|
||||
int readerfd;
|
||||
int writerfd;
|
||||
struct ast_frame f;
|
||||
unsigned char frame_data[CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET + RTP_HEADER_SIZE];
|
||||
|
||||
ast_cond_t event_trigger;
|
||||
unsigned int waitevent;
|
||||
|
||||
char name[CAPI_MAX_STRING];
|
||||
char vname[CAPI_MAX_STRING];
|
||||
unsigned char tmpbuf[CAPI_MAX_STRING];
|
||||
|
||||
/*! Channel who used us, possibly NULL */
|
||||
struct ast_channel *used;
|
||||
/*! Channel we belong to, possibly NULL */
|
||||
struct ast_channel *owner;
|
||||
/*! Frame */
|
||||
struct ast_frame fr;
|
||||
/*! Channel who called us, possibly NULL */
|
||||
struct ast_channel *peer;
|
||||
/*! Set if structure is reserved */
|
||||
volatile int reserved;
|
||||
|
||||
/* capi message number */
|
||||
_cword MessageNumber;
|
||||
|
@ -213,22 +414,25 @@ struct capi_pvt {
|
|||
/* on which controller we do live */
|
||||
int controller;
|
||||
|
||||
/* we could live on those */
|
||||
unsigned long controllers;
|
||||
|
||||
/* send buffer */
|
||||
unsigned char send_buffer[CAPI_MAX_B3_BLOCKS * CAPI_MAX_B3_BLOCK_SIZE];
|
||||
unsigned char send_buffer[CAPI_MAX_B3_BLOCKS *
|
||||
(CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET)];
|
||||
unsigned short send_buffer_handle;
|
||||
|
||||
/* receive buffer */
|
||||
unsigned char rec_buffer[CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET];
|
||||
unsigned char rec_buffer[CAPI_MAX_B3_BLOCK_SIZE + AST_FRIENDLY_OFFSET + RTP_HEADER_SIZE];
|
||||
|
||||
/* current state */
|
||||
int state;
|
||||
|
||||
/* the state of the line */
|
||||
unsigned int isdnstate;
|
||||
unsigned int isdnstate2;
|
||||
int cause;
|
||||
|
||||
|
||||
/* which b-protocol is active */
|
||||
int bproto;
|
||||
|
||||
char context[AST_MAX_EXTENSION];
|
||||
/*! Multiple Subscriber Number we listen to (, seperated list) */
|
||||
char incomingmsn[CAPI_MAX_STRING];
|
||||
|
@ -245,11 +449,15 @@ struct capi_pvt {
|
|||
int cid_ton;
|
||||
|
||||
char accountcode[20];
|
||||
int amaflags;
|
||||
|
||||
unsigned int callgroup;
|
||||
unsigned int group;
|
||||
ast_group_t callgroup;
|
||||
ast_group_t pickupgroup;
|
||||
ast_group_t group;
|
||||
|
||||
/*! default language */
|
||||
ast_group_t transfergroup;
|
||||
|
||||
/* language */
|
||||
char language[MAX_LANGUAGE];
|
||||
|
||||
/* additional numbers to dial */
|
||||
|
@ -259,8 +467,6 @@ struct capi_pvt {
|
|||
int calledPartyIsISDN;
|
||||
/* this is an outgoing channel */
|
||||
int outgoing;
|
||||
/* are we doing early B3 connect on this interface? */
|
||||
int earlyB3;
|
||||
/* should we do early B3 on this interface? */
|
||||
int doB3;
|
||||
/* store plci here for the call that is onhold */
|
||||
|
@ -269,6 +475,7 @@ struct capi_pvt {
|
|||
int doDTMF;
|
||||
/* CAPI echo cancellation */
|
||||
int doEC;
|
||||
int doEC_global;
|
||||
int ecOption;
|
||||
int ecTail;
|
||||
int ecSelector;
|
||||
|
@ -288,21 +495,31 @@ struct capi_pvt {
|
|||
|
||||
/* Common ISDN Profile (CIP) */
|
||||
int cip;
|
||||
unsigned short transfercapability;
|
||||
|
||||
/* Features and settings of current connection */
|
||||
unsigned int fsetting;
|
||||
|
||||
/* if not null, receiving a fax */
|
||||
FILE *fFax;
|
||||
/* Has a fax tone already been handled? */
|
||||
int faxhandled;
|
||||
/* Fax ready ? */
|
||||
int FaxState;
|
||||
/* Fax status */
|
||||
unsigned int FaxState;
|
||||
/* Window for fax detection */
|
||||
unsigned int faxdetecttime;
|
||||
/* custom fax context,exten,prio */
|
||||
char faxcontext[AST_MAX_EXTENSION+1];
|
||||
char faxexten[AST_MAX_EXTENSION+1];
|
||||
int faxpriority;
|
||||
|
||||
/* handle for CCBS/CCNR callback */
|
||||
unsigned int ccbsnrhandle;
|
||||
|
||||
/* not all codecs supply frames in nice 160 byte chunks */
|
||||
struct ast_smoother *smoother;
|
||||
/* ok, we stop to be nice and give them the lowest possible latency 130 samples * 2 = 260 bytes */
|
||||
|
||||
/* outgoing queue count */
|
||||
int B3q;
|
||||
ast_mutex_t lockB3q;
|
||||
int B3count;
|
||||
|
||||
/* do ECHO SURPRESSION */
|
||||
int ES;
|
||||
|
@ -310,6 +527,27 @@ struct capi_pvt {
|
|||
short txavg[ECHO_TX_COUNT];
|
||||
float rxmin;
|
||||
float txmin;
|
||||
|
||||
unsigned short divaAudioFlags;
|
||||
unsigned short divaDataStubAudioFlags;
|
||||
unsigned short divaDigitalRxGain;
|
||||
float divaDigitalRxGainDB;
|
||||
unsigned short divaDigitalTxGain;
|
||||
float divaDigitalTxGainDB;
|
||||
unsigned short rxPitch;
|
||||
unsigned short txPitch;
|
||||
char special_tone_extension[AST_MAX_EXTENSION+1];
|
||||
|
||||
char channel_command_digits[AST_MAX_EXTENSION+1];
|
||||
time_t channel_command_timestamp;
|
||||
int channel_command_digit;
|
||||
int command_pass_digits;
|
||||
diva_entity_queue_t channel_command_q;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
struct ast_jb_conf jbconf;
|
||||
char mohinterpret[MAX_MUSICCLASS];
|
||||
#endif
|
||||
|
||||
struct cc_capi_gains g;
|
||||
|
||||
|
@ -320,6 +558,42 @@ struct capi_pvt {
|
|||
unsigned int reason;
|
||||
unsigned int reasonb3;
|
||||
|
||||
/* deferred tasks */
|
||||
time_t whentohangup;
|
||||
time_t whentoqueuehangup;
|
||||
time_t whentoretrieve;
|
||||
|
||||
/* RTP */
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
struct ast_rtp_instance *rtp;
|
||||
#else
|
||||
struct ast_rtp *rtp;
|
||||
#endif
|
||||
cc_format_t capability;
|
||||
int rtpcodec;
|
||||
int codec;
|
||||
unsigned int timestamp;
|
||||
|
||||
/* Q.SIG features */
|
||||
int qsigfeat;
|
||||
int divaqsig;
|
||||
struct cc_qsig_data qsig_data;
|
||||
|
||||
/* Resource PLCI data */
|
||||
int resource_plci_type; /* NULL PLCI, DATA, LINE */
|
||||
|
||||
/* Resource PLCI line if data */
|
||||
struct capi_pvt *line_plci;
|
||||
/* Resource PLCI data data if line */
|
||||
struct capi_pvt *data_plci;
|
||||
|
||||
#ifdef DIVA_STREAMING
|
||||
struct _diva_stream_scheduling_entry* diva_stream_entry;
|
||||
#endif
|
||||
/* Connection between two conference rooms. NULL PLCI */
|
||||
int virtualBridgePeer;
|
||||
struct capi_pvt *bridgePeer;
|
||||
|
||||
/*! Next channel in list */
|
||||
struct capi_pvt *next;
|
||||
};
|
||||
|
@ -336,10 +610,15 @@ struct cc_capi_profile {
|
|||
unsigned int b3protocols;
|
||||
unsigned int reserved3[6];
|
||||
unsigned int manufacturer[5];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct cc_capi_qsig_conf {
|
||||
char if_pr_propose_pn[AST_MAX_EXTENSION];
|
||||
};
|
||||
|
||||
struct cc_capi_conf {
|
||||
char name[CAPI_MAX_STRING];
|
||||
char language[MAX_LANGUAGE];
|
||||
char incomingmsn[CAPI_MAX_STRING];
|
||||
char defaultcid[CAPI_MAX_STRING];
|
||||
char context[AST_MAX_EXTENSION];
|
||||
|
@ -351,6 +630,7 @@ struct cc_capi_conf {
|
|||
int echocancel;
|
||||
int ecoption;
|
||||
int ectail;
|
||||
int ecnlp;
|
||||
int ecSelector;
|
||||
int isdnmode;
|
||||
int ntmode;
|
||||
|
@ -358,20 +638,85 @@ struct cc_capi_conf {
|
|||
int holdtype;
|
||||
int es;
|
||||
int bridge;
|
||||
unsigned int callgroup;
|
||||
unsigned int group;
|
||||
int amaflags;
|
||||
int qsigfeat;
|
||||
int divaqsig;
|
||||
struct cc_capi_qsig_conf qsigconf;
|
||||
unsigned int faxsetting;
|
||||
unsigned int faxdetecttime;
|
||||
/* custom fax context,exten,prio */
|
||||
char faxcontext[AST_MAX_EXTENSION+1];
|
||||
char faxexten[AST_MAX_EXTENSION+1];
|
||||
int faxpriority;
|
||||
ast_group_t callgroup;
|
||||
ast_group_t pickupgroup;
|
||||
ast_group_t group;
|
||||
ast_group_t transfergroup;
|
||||
float rxgain;
|
||||
float txgain;
|
||||
#ifndef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_codec_pref prefs;
|
||||
#endif
|
||||
#ifdef CC_AST_HAS_FORMAT_T
|
||||
format_t capability;
|
||||
#else
|
||||
int capability;
|
||||
#endif
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
struct ast_jb_conf jbconf;
|
||||
char mohinterpret[MAX_MUSICCLASS];
|
||||
#endif
|
||||
int echocancelpath;
|
||||
int econtransitconn;
|
||||
|
||||
int mwifacptynrtype;
|
||||
int mwifacptynrton;
|
||||
int mwifacptynrpres;
|
||||
int mwibasicservice;
|
||||
int mwiinvocation;
|
||||
|
||||
char* mwimailbox;
|
||||
|
||||
int hlimit;
|
||||
int slimit;
|
||||
};
|
||||
|
||||
struct cc_capi_controller;
|
||||
struct _cc_capi_mwi_mailbox;
|
||||
typedef struct _cc_capi_mwi_mailbox {
|
||||
AST_LIST_ENTRY(_cc_capi_mwi_mailbox) link;
|
||||
const struct cc_capi_controller *controller;
|
||||
unsigned short basicService;
|
||||
unsigned short invocationMode;
|
||||
unsigned char *mailboxNumber;
|
||||
char *mailboxContext;
|
||||
unsigned char *controllingUserNumber;
|
||||
unsigned char *controllingUserProvidedNumber;
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
struct ast_event_sub* mwiSubscribtion;
|
||||
#else
|
||||
void* mwiSubscribtion;
|
||||
#endif
|
||||
} cc_capi_mwi_mailbox_t;
|
||||
|
||||
struct cc_capi_controller {
|
||||
/* which controller is this? */
|
||||
int controller;
|
||||
/* is this controller used? */
|
||||
int used;
|
||||
/* how many bchans? */
|
||||
int nbchannels;
|
||||
/* free bchans */
|
||||
int nfreebchannels;
|
||||
/* Controller considered BUSY amount if free channels below
|
||||
of this level */
|
||||
int nfreebchannelsHardThr;
|
||||
/* If amount of free channels is below this level then
|
||||
try to allocate call on other controler in group
|
||||
where this level is not reached or difference is less */
|
||||
int nfreebchannelsSoftThr;
|
||||
/* features: */
|
||||
int broadband;
|
||||
int dtmf;
|
||||
int echocancel;
|
||||
int sservices; /* supplementray services */
|
||||
|
@ -388,20 +733,25 @@ struct cc_capi_controller {
|
|||
int MWI;
|
||||
int CCNR;
|
||||
int CONF;
|
||||
/* RTP */
|
||||
int rtpcodec;
|
||||
|
||||
int divaExtendedFeaturesAvailable;
|
||||
int ecPath;
|
||||
int ecOnTransit;
|
||||
int fax_t30_extended;
|
||||
#ifdef DIVA_STREAMING
|
||||
int divaStreaming;
|
||||
#endif
|
||||
AST_LIST_HEAD_NOLOCK(, _cc_capi_mwi_mailbox) mwiSubscribtions;
|
||||
#ifdef DIVA_STATUS
|
||||
int interfaceState;
|
||||
int hwState;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* ETSI 300 102-1 information element identifiers */
|
||||
#define CAPI_ETSI_IE_CAUSE 0x08
|
||||
#define CAPI_ETSI_IE_PROGRESS_INDICATOR 0x1e
|
||||
#define CAPI_ETSI_IE_CALLED_PARTY_NUMBER 0x70
|
||||
|
||||
/* ETIS 300 102-1 message types */
|
||||
#define CAPI_ETSI_ALERTING 0x01
|
||||
#define CAPI_ETSI_SETUP_ACKKNOWLEDGE 0x0d
|
||||
#define CAPI_ETSI_DISCONNECT 0x45
|
||||
|
||||
/* ETSI 300 102-1 Numbering Plans */
|
||||
#define CAPI_ETSI_NPLAN_SUBSCRIBER 0x40
|
||||
#define CAPI_ETSI_NPLAN_NATIONAL 0x20
|
||||
#define CAPI_ETSI_NPLAN_INTERNAT 0x10
|
||||
|
||||
|
@ -437,4 +787,98 @@ struct cc_capi_controller {
|
|||
#define PRI_TRANS_CAP_DIGITAL_W_TONES 0x11
|
||||
#define PRI_TRANS_CAP_VIDEO 0x18
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern
|
||||
#ifndef CC_AST_HAS_VERSION_10_0
|
||||
const
|
||||
#endif
|
||||
struct ast_channel_tech capi_tech;
|
||||
#ifdef CC_AST_HAS_FORMAT_T
|
||||
extern format_t capi_capability;
|
||||
#else
|
||||
extern int capi_capability;
|
||||
#endif
|
||||
extern unsigned capi_ApplID;
|
||||
extern struct capi_pvt *capi_iflist;
|
||||
extern void cc_start_b3(struct capi_pvt *i);
|
||||
extern unsigned char capi_tcap_is_digital(unsigned short tcap);
|
||||
extern void capi_queue_cause_control(struct capi_pvt *i, int control);
|
||||
extern void capidev_handle_connection_conf(struct capi_pvt **i, unsigned int PLCI,
|
||||
unsigned short wInfo, unsigned short wMsgNum, struct ast_channel** interface_owner);
|
||||
extern void capi_wait_for_answered(struct capi_pvt *i);
|
||||
extern int capi_wait_for_b3_up(struct capi_pvt *i);
|
||||
extern void capi_activehangup(struct capi_pvt *i, int state);
|
||||
extern void capi_gains(struct cc_capi_gains *g, float rxgain, float txgain);
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
extern char chatinfo_usage[];
|
||||
#endif
|
||||
|
||||
typedef int (*pbx_capi_command_proc_t)(struct ast_channel *, char *);
|
||||
pbx_capi_command_proc_t pbx_capi_lockup_command_by_name(const char* name);
|
||||
/*!
|
||||
* \brief returns list of supported by this controller RTP codecs
|
||||
*/
|
||||
cc_format_t pbx_capi_get_controller_codecs(int controller);
|
||||
_cstruct diva_get_b1_conf(struct capi_pvt *i);
|
||||
/*!
|
||||
\brief &capi_controllers[controller]
|
||||
*/
|
||||
const struct cc_capi_controller *pbx_capi_get_controller(int controller);
|
||||
/*!
|
||||
\brief capi_num_controllers
|
||||
*/
|
||||
int pbx_capi_get_num_controllers(void);
|
||||
/*!
|
||||
\brief tdesc
|
||||
*/
|
||||
const char* pbx_capi_get_module_description(void);
|
||||
/*!
|
||||
\brief cc_mutex_lock(&iflock)
|
||||
*/
|
||||
void pbx_capi_lock_interfaces(void);
|
||||
/*!
|
||||
\brief cc_mutex_unlock(&iflock)
|
||||
*/
|
||||
void pbx_capi_unlock_interfaces(void);
|
||||
/*!
|
||||
\brief Exec cappicommand using CLI
|
||||
*/
|
||||
int pbx_capi_cli_exec_capicommand(struct ast_channel *chan, const char *data);
|
||||
|
||||
/*!
|
||||
\brief EC control
|
||||
*/
|
||||
void capi_echo_canceller(struct capi_pvt *i, int function);
|
||||
|
||||
#ifdef DIVA_STREAMING
|
||||
struct _diva_streaming_vector;
|
||||
void capidev_handle_data_b3_indication_vector (struct capi_pvt *i,
|
||||
struct _diva_streaming_vector* vind,
|
||||
int vind_nr);
|
||||
/*!
|
||||
* \brief Return true if Diva streaming supported by CAPI controller
|
||||
*/
|
||||
int pbx_capi_streaming_supported (struct capi_pvt *i);
|
||||
#endif
|
||||
|
||||
/* DIVA specific MANUFACTURER definitions */
|
||||
#define _DI_MANU_ID 0x44444944
|
||||
#define _DI_ASSIGN_PLCI 0x0001
|
||||
#define _DI_DSP_CTRL 0x0003
|
||||
#define _DI_OPTIONS_REQUEST 0x0009
|
||||
|
||||
#if (!defined(CC_AST_HAS_VERSION_1_4) && !defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
|
||||
|
||||
#define ast_malloc(__x__) malloc((__x__))
|
||||
#define ast_free(__x__) free((__x__))
|
||||
#define ast_strdup(__x__) strdup((__x__))
|
||||
#define ast_channel_trylock(__x__) ast_mutex_trylock(&(__x__)->lock)
|
||||
#define ast_channel_unlock(__x__) ast_mutex_unlock(&(__x__)->lock)
|
||||
#define ast_devstate_prov_add(__a__,__b__) (-1)
|
||||
#define ast_devstate_prov_del(__x__) do{}while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Based on apps/app_meetme.c
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_chat.h"
|
||||
#include "chan_capi_management_common.h"
|
||||
#include "asterisk/manager.h"
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
|
||||
#define CC_AMI_ACTION_NAME_CHATLIST "CapichatList"
|
||||
#define CC_AMI_ACTION_NAME_CHATMUTE "CapichatMute"
|
||||
#define CC_AMI_ACTION_NAME_CHATUNMUTE "CapichatUnmute"
|
||||
#define CC_AMI_ACTION_NAME_CHATREMOVE "CapichatRemove"
|
||||
#define CC_AMI_ACTION_NAME_CAPICOMMAND "CapiCommand"
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m);
|
||||
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m);
|
||||
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m);
|
||||
static int pbx_capi_ami_capichat_remove(struct mansession *s, const struct message *m);
|
||||
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute);
|
||||
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m);
|
||||
static int capiChatListRegistered;
|
||||
static int capiChatMuteRegistered;
|
||||
static int capiChatUnmuteRegistered;
|
||||
static int capiChatRemoveRegistered;
|
||||
static int capiCommandRegistered;
|
||||
|
||||
static char mandescr_capichatlist[] =
|
||||
"Description: Lists all users in a particular CapiChat conference.\n"
|
||||
"CapichatList will follow as separate events, followed by a final event called\n"
|
||||
"CapichatListComplete.\n"
|
||||
"Variables:\n"
|
||||
" *ActionId: <id>\n"
|
||||
" *Conference: <confname>\n";
|
||||
|
||||
static char mandescr_capichatmute[] =
|
||||
"Description: Mutes user in a particular CapiChat conference.\n"
|
||||
"Variables:\n"
|
||||
" *ActionId: <id>\n"
|
||||
" *Conference: <confname>\n"
|
||||
" *Member: <membername>\n"
|
||||
" *Path: <Rx or Tx>\n";
|
||||
|
||||
static char mandescr_capichatunmute[] =
|
||||
"Description: Unmutes user in a particular CapiChat conference.\n"
|
||||
"Variables:\n"
|
||||
" *ActionId: <id>\n"
|
||||
" *Conference: <confname>\n"
|
||||
" *Member: <membername>\n"
|
||||
" *Path: <Rx or Tx>\n";
|
||||
|
||||
static char mandescr_capichatremove[] =
|
||||
"Description: Removes user in a particular CapiChat conference.\n"
|
||||
"Variables:\n"
|
||||
" *ActionId: <id>\n"
|
||||
" *Conference: <confname>\n"
|
||||
" *Member: <membername>\n";
|
||||
|
||||
static char mandescr_capicommand[] =
|
||||
"Description: Exec capicommand.\n"
|
||||
"Variables:\n"
|
||||
" *ActionId: <id>\n"
|
||||
" *Channel: <channame>\n"
|
||||
" *Capicommand: <capicommand>\n";
|
||||
|
||||
void pbx_capi_ami_register(struct ast_module *myself)
|
||||
{
|
||||
capiChatListRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATLIST,
|
||||
EVENT_FLAG_REPORTING,
|
||||
pbx_capi_ami_capichat_list,
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
myself,
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
"List participants in a conference",
|
||||
mandescr_capichatlist) == 0;
|
||||
|
||||
capiChatMuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATMUTE,
|
||||
EVENT_FLAG_CALL,
|
||||
pbx_capi_ami_capichat_mute,
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
myself,
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
"Mute a conference user",
|
||||
mandescr_capichatmute) == 0;
|
||||
|
||||
capiChatUnmuteRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATUNMUTE,
|
||||
EVENT_FLAG_CALL,
|
||||
pbx_capi_ami_capichat_unmute,
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
myself,
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
"Unmute a conference user",
|
||||
mandescr_capichatunmute) == 0;
|
||||
|
||||
capiChatRemoveRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CHATREMOVE,
|
||||
EVENT_FLAG_CALL,
|
||||
pbx_capi_ami_capichat_remove,
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
myself,
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
"Remove a conference user",
|
||||
mandescr_capichatremove) == 0;
|
||||
|
||||
capiCommandRegistered = ast_manager_register2(CC_AMI_ACTION_NAME_CAPICOMMAND,
|
||||
EVENT_FLAG_CALL,
|
||||
pbx_capi_ami_capicommand,
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
myself,
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
"Exec capicommand",
|
||||
mandescr_capicommand) == 0;
|
||||
}
|
||||
|
||||
void pbx_capi_ami_unregister(void)
|
||||
{
|
||||
if (capiChatListRegistered != 0)
|
||||
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATLIST);
|
||||
|
||||
if (capiChatMuteRegistered != 0)
|
||||
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATMUTE);
|
||||
|
||||
if (capiChatUnmuteRegistered != 0)
|
||||
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATUNMUTE);
|
||||
|
||||
if (capiChatRemoveRegistered != 0)
|
||||
ast_manager_unregister(CC_AMI_ACTION_NAME_CHATREMOVE);
|
||||
|
||||
if (capiCommandRegistered != 0)
|
||||
ast_manager_unregister(CC_AMI_ACTION_NAME_CAPICOMMAND);
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capichat_list(struct mansession *s, const struct message *m) {
|
||||
const char *actionid = astman_get_header(m, "ActionID");
|
||||
const char *conference = astman_get_header(m, "Conference");
|
||||
char idText[80] = "";
|
||||
int total = 0;
|
||||
const struct capichat_s *capiChatRoom;
|
||||
|
||||
if (!ast_strlen_zero(actionid))
|
||||
snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
|
||||
|
||||
if (pbx_capi_chat_get_room_c(NULL) == NULL) {
|
||||
astman_send_error(s, m, "No active conferences.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
astman_send_listack(s, m, CC_AMI_ACTION_NAME_CHATLIST" user list will follow", "start");
|
||||
|
||||
/* Find the right conference */
|
||||
pbx_capi_lock_chat_rooms();
|
||||
|
||||
for (capiChatRoom = pbx_capi_chat_get_room_c(NULL), total = 0;
|
||||
capiChatRoom != NULL;
|
||||
capiChatRoom = pbx_capi_chat_get_room_c(capiChatRoom)) {
|
||||
const char* roomName = pbx_capi_chat_get_room_name(capiChatRoom);
|
||||
/* If we ask for one particular, and this isn't it, skip it */
|
||||
if (!ast_strlen_zero(conference) && strcmp(roomName, conference))
|
||||
continue;
|
||||
|
||||
{
|
||||
unsigned int roomNumber = pbx_capi_chat_get_room_number(capiChatRoom);
|
||||
struct ast_channel *c = pbx_capi_chat_get_room_channel(capiChatRoom);
|
||||
const struct capi_pvt* i = pbx_capi_chat_get_room_interface_c(capiChatRoom);
|
||||
int isMemberOperator = pbx_capi_chat_is_member_operator(capiChatRoom);
|
||||
int isCapiChatRoomMuted = pbx_capi_chat_is_room_muted(capiChatRoom);
|
||||
int isCapiChatMemberMuted = pbx_capi_chat_is_member_muted(capiChatRoom);
|
||||
int isCapiChatMemberListener = pbx_capi_chat_is_member_listener(capiChatRoom);
|
||||
int isCapiChatMostRecentMember = pbx_capi_chat_is_most_recent_user(capiChatRoom);
|
||||
const char* mutedVisualName = "No";
|
||||
char* cidVisual;
|
||||
char* callerNameVisual;
|
||||
|
||||
if ((c == NULL) || (i == NULL))
|
||||
continue;
|
||||
|
||||
cidVisual = ast_strdup(pbx_capi_get_cid (c, "<unknown>"));
|
||||
callerNameVisual = ast_strdup(pbx_capi_get_callername (c, "<no name>"));
|
||||
|
||||
if (isCapiChatMemberListener || isCapiChatRoomMuted || isCapiChatMemberMuted) {
|
||||
if (isMemberOperator) {
|
||||
if (isCapiChatMemberMuted)
|
||||
mutedVisualName = "By self";
|
||||
} else if (isCapiChatMemberListener || isCapiChatRoomMuted) {
|
||||
mutedVisualName = "By admin";
|
||||
} else {
|
||||
mutedVisualName = "By self";
|
||||
}
|
||||
}
|
||||
|
||||
total++;
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const char *cur_name = ast_channel_name(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const char *cur_name = c->name;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
astman_append(s,
|
||||
"Event: "CC_AMI_ACTION_NAME_CHATLIST"\r\n"
|
||||
"%s"
|
||||
"Conference: %s/%u\r\n"
|
||||
"UserNumber: %d\r\n"
|
||||
"CallerIDNum: %s\r\n"
|
||||
"CallerIDName: %s\r\n"
|
||||
"Channel: %s\r\n"
|
||||
"Admin: %s\r\n"
|
||||
"Role: %s\r\n"
|
||||
"MarkedUser: %s\r\n"
|
||||
"Muted: %s\r\n"
|
||||
"Talking: %s\r\n"
|
||||
"Domain: %s\r\n"
|
||||
"DTMF: %s\r\n"
|
||||
"EchoCancel: %s\r\n"
|
||||
"NoiseSupp: %s\r\n"
|
||||
"RxAGC: %s\r\n"
|
||||
"TxAGC: %s\r\n"
|
||||
"RxGain: %.1f%s\r\n"
|
||||
"TxGain: %.1f%s\r\n"
|
||||
"\r\n",
|
||||
idText,
|
||||
roomName,
|
||||
roomNumber,
|
||||
total,
|
||||
(cidVisual != 0) ? cidVisual : "?",
|
||||
(callerNameVisual != 0) ? callerNameVisual : "?",
|
||||
cur_name,
|
||||
(isMemberOperator != 0) ? "Yes" : "No",
|
||||
(isCapiChatMemberListener != 0) ? "Listen only" : "Talk and listen" /* "Talk only" */,
|
||||
(isCapiChatMostRecentMember != 0) ? "Yes" : "No",
|
||||
mutedVisualName,
|
||||
/* "Yes" "No" */ "Not monitored",
|
||||
(i->channeltype == CAPI_CHANNELTYPE_B) ? "TDM" : "IP",
|
||||
(i->isdnstate & CAPI_ISDN_STATE_DTMF) ? "Y" : "N",
|
||||
(i->isdnstate & CAPI_ISDN_STATE_EC) ? "Y" : "N",
|
||||
(i->divaAudioFlags & 0x0080) ? "Y" : "N", /* Noise supression */
|
||||
(i->divaAudioFlags & 0x0008) ? "Y" : "N", /* Rx AGC */
|
||||
(i->divaAudioFlags & 0x0004) ? "Y" : "N", /* Tx AGC */
|
||||
i->divaDigitalRxGainDB, "dB",
|
||||
i->divaDigitalTxGainDB, "dB");
|
||||
|
||||
ast_free (cidVisual);
|
||||
ast_free (callerNameVisual);
|
||||
}
|
||||
}
|
||||
pbx_capi_unlock_chat_rooms();
|
||||
/* Send final confirmation */
|
||||
astman_append(s,
|
||||
"Event: "CC_AMI_ACTION_NAME_CHATLIST"Complete\r\n"
|
||||
"EventList: Complete\r\n"
|
||||
"ListItems: %d\r\n"
|
||||
"%s"
|
||||
"\r\n", total, idText);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capichat_mute(struct mansession *s, const struct message *m)
|
||||
{
|
||||
return pbx_capi_ami_capichat_control(s, m, 1);
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capichat_unmute(struct mansession *s, const struct message *m)
|
||||
{
|
||||
return pbx_capi_ami_capichat_control(s, m, 0);
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capichat_control(struct mansession *s, const struct message *m, int chatMute)
|
||||
{
|
||||
const char *roomName = astman_get_header(m, "Conference");
|
||||
const char *userName = astman_get_header(m, "Member");
|
||||
const char *voicePath = astman_get_header(m, "Path");
|
||||
const char* capiCommand;
|
||||
int ret;
|
||||
|
||||
if (ast_strlen_zero(roomName)) {
|
||||
astman_send_error(s, m, "Capi Chat conference not specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(userName)) {
|
||||
char* param = ast_strdupa((chatMute != 0) ? "yes" : "no");
|
||||
int ret = pbx_capi_chat_mute(NULL, param);
|
||||
if (ret == 0) {
|
||||
astman_send_ack(s, m, (chatMute != 0) ? "Conference muted" : "Conference unmuted");
|
||||
} else {
|
||||
astman_send_error(s, m, "Failed to change mode of Capi Chat conference");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((voicePath != NULL) && (strcmp(voicePath, "Rx") == 0)) {
|
||||
capiCommand = (chatMute != 0) ? "rxdgain,-128" : "rxdgain,0";
|
||||
} else {
|
||||
capiCommand = (chatMute != 0) ? "txdgain,-128" : "txdgain,0";
|
||||
}
|
||||
|
||||
ret = pbx_capi_management_capicommand(userName, capiCommand);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
astman_send_ack(s, m, (chatMute != 0) ? "User muted" : "User unmuted");
|
||||
break;
|
||||
|
||||
case -4:
|
||||
astman_send_error(s, m, "User not found");
|
||||
break;
|
||||
|
||||
default:
|
||||
astman_send_error(s, m, "Command error");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capichat_remove(struct mansession *s, const struct message *m)
|
||||
{
|
||||
const char *roomName = astman_get_header(m, "Conference");
|
||||
const char *userName = astman_get_header(m, "Member");
|
||||
int ret;
|
||||
|
||||
if (ast_strlen_zero(roomName)) {
|
||||
astman_send_error(s, m, "Capi Chat conference not specified");
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(userName)) {
|
||||
astman_send_error(s, m, "Capi Chat member not specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pbx_capi_chat_remove_user (roomName, userName);
|
||||
if (ret == 0) {
|
||||
astman_send_ack(s, m, "Member removed");
|
||||
} else {
|
||||
astman_send_error(s, m, "Member not found");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pbx_capi_ami_capicommand(struct mansession *s, const struct message *m)
|
||||
{
|
||||
const char *requiredChannelName = astman_get_header(m, "Channel");
|
||||
const char *chancapiCommand = astman_get_header(m, "Command");
|
||||
int ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
astman_send_ack(s, m, "OK");
|
||||
break;
|
||||
|
||||
case -2:
|
||||
astman_send_error(s, m, "Channel name not specified");
|
||||
break;
|
||||
|
||||
case -3:
|
||||
astman_send_error(s, m, "Capi command name not specified");
|
||||
break;
|
||||
|
||||
case -4:
|
||||
astman_send_error(s, m, "Channel not found");
|
||||
break;
|
||||
|
||||
case -1:
|
||||
default:
|
||||
astman_send_error(s, m, "Command error");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
void pbx_capi_ami_register(struct ast_module *myself)
|
||||
{
|
||||
}
|
||||
void pbx_capi_ami_unregister(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void pbx_capi_chat_join_event(struct ast_channel* c, const struct capichat_s * room)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const char *cur_name = ast_channel_name(c);
|
||||
const char *cur_uniqid = ast_channel_uniqueid(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const char *cur_name = c->name;
|
||||
const char *cur_uniqid = c->uniqueid;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_8
|
||||
ast_manager_event(c,
|
||||
#else
|
||||
manager_event(
|
||||
#endif
|
||||
EVENT_FLAG_CALL, "CapichatJoin",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n"
|
||||
"Conference: %s\r\n"
|
||||
"Conferencenum: %u\r\n"
|
||||
"CallerIDnum: %s\r\n"
|
||||
"CallerIDname: %s\r\n",
|
||||
cur_name, cur_uniqid,
|
||||
pbx_capi_chat_get_room_name(room),
|
||||
pbx_capi_chat_get_room_number(room),
|
||||
pbx_capi_get_cid (c, "<unknown>"),
|
||||
pbx_capi_get_callername (c, "<no name>"));
|
||||
}
|
||||
|
||||
void pbx_capi_chat_leave_event(struct ast_channel* c,
|
||||
const struct capichat_s *room,
|
||||
long duration)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const char *cur_name = ast_channel_name(c);
|
||||
const char *cur_uniqid = ast_channel_uniqueid(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const char *cur_name = c->name;
|
||||
const char *cur_uniqid = c->uniqueid;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_8
|
||||
ast_manager_event(c,
|
||||
#else
|
||||
manager_event(
|
||||
#endif
|
||||
EVENT_FLAG_CALL, "CapichatLeave",
|
||||
"Channel: %s\r\n"
|
||||
"Uniqueid: %s\r\n"
|
||||
"Conference: %s\r\n"
|
||||
"Conferencenum: %u\r\n"
|
||||
"CallerIDNum: %s\r\n"
|
||||
"CallerIDName: %s\r\n"
|
||||
"Duration: %ld\r\n",
|
||||
cur_name, cur_uniqid,
|
||||
pbx_capi_chat_get_room_name(room),
|
||||
pbx_capi_chat_get_room_number(room),
|
||||
pbx_capi_get_cid (c, "<unknown>"),
|
||||
pbx_capi_get_callername (c, "<no name>"),
|
||||
duration);
|
||||
}
|
||||
|
||||
void pbx_capi_chat_conference_end_event(const char* roomName)
|
||||
{
|
||||
manager_event(EVENT_FLAG_CALL, "CapichatEnd", "Conference: %s\r\n", roomName);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*
|
||||
* Based on apps/app_meetme.c
|
||||
*
|
||||
*/
|
||||
#ifndef __CC_AMI_INTERFACE_H__
|
||||
#define __CC_AMI_INTERFACE_H__
|
||||
|
||||
void pbx_capi_ami_register(struct ast_module *myself);
|
||||
void pbx_capi_ami_unregister(void);
|
||||
struct capichat_s;
|
||||
void pbx_capi_chat_join_event(struct ast_channel* c, const struct capichat_s * room);
|
||||
void pbx_capi_chat_leave_event(struct ast_channel* c,
|
||||
const struct capichat_s *room,
|
||||
long duration);
|
||||
void pbx_capi_chat_conference_end_event(const char* roomName);
|
||||
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _PBX_CAPI_CHAT_H
|
||||
#define _PBX_CAPI_CHAT_H
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern void pbx_capi_chat_init_module(void);
|
||||
extern int pbx_capi_chat(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_chat_associate_resource_plci(struct ast_channel *c, char *param);
|
||||
extern struct capi_pvt* pbx_check_resource_plci(struct ast_channel *c);
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
extern char *pbxcli_capi_chatinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
#else
|
||||
extern int pbxcli_capi_chatinfo(int fd, int argc, char *argv[]);
|
||||
#endif
|
||||
extern int pbx_capi_chat_command (struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_chat_mute(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_chat_play(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_chat_connect(struct ast_channel *c, char *param);
|
||||
int pbx_capi_chat_remove_user(const char* room, const char* name);
|
||||
|
||||
struct capichat_s;
|
||||
const struct capichat_s *pbx_capi_chat_get_room_c(const struct capichat_s * room);
|
||||
const char* pbx_capi_chat_get_room_name(const struct capichat_s * room);
|
||||
unsigned int pbx_capi_chat_get_room_number(const struct capichat_s * room);
|
||||
unsigned int pbx_capi_chat_get_room_members(const struct capichat_s * room);
|
||||
struct ast_channel *pbx_capi_chat_get_room_channel(const struct capichat_s * room);
|
||||
const struct capi_pvt* pbx_capi_chat_get_room_interface_c(const struct capichat_s * room);
|
||||
int pbx_capi_chat_is_member_operator(const struct capichat_s * room);
|
||||
int pbx_capi_chat_is_room_muted(const struct capichat_s * room);
|
||||
int pbx_capi_chat_is_member_muted(const struct capichat_s * room);
|
||||
int pbx_capi_chat_is_member_listener(const struct capichat_s * room);
|
||||
int pbx_capi_chat_is_most_recent_user(const struct capichat_s * room);
|
||||
unsigned int pbx_capi_chat_get_room_group (const struct capichat_s * room);
|
||||
unsigned int pbx_capi_chat_get_room_group_members (const struct capichat_s * room);
|
||||
|
||||
void pbx_capi_lock_chat_rooms(void);
|
||||
void pbx_capi_unlock_chat_rooms(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,842 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2010 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* Reworked, but based on the work of
|
||||
* Copyright (C) 2002-2005 Junghanns.NET GmbH
|
||||
*
|
||||
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_chat.h"
|
||||
#include "chan_capi_cli.h"
|
||||
#include "chan_capi_management_common.h"
|
||||
#ifdef DIVA_STREAMING
|
||||
#include "platform.h"
|
||||
#include "chan_capi_divastreaming_utils.h"
|
||||
#endif
|
||||
#ifdef DIVA_STATUS
|
||||
#include "divastatus_ifc.h"
|
||||
#endif
|
||||
#ifdef DIVA_VERBOSE
|
||||
#include "divaverbose.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* usages
|
||||
*/
|
||||
static char info_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " info\n"
|
||||
" Show info about B channels on controllers.\n";
|
||||
|
||||
static char show_channels_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " show channels\n"
|
||||
" Show info about B channels.\n";
|
||||
|
||||
static char show_resources_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " show ressources\n"
|
||||
" Show info about used by channels resources.\n";
|
||||
|
||||
static char show_bridges_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " show bridges\n"
|
||||
" Show info about used conference bridges.\n";
|
||||
|
||||
static char debug_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " debug\n"
|
||||
" Enables dumping of " CC_MESSAGE_BIGNAME " packets for debugging purposes\n";
|
||||
|
||||
static char no_debug_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " no debug\n"
|
||||
" Disables dumping of " CC_MESSAGE_BIGNAME " packets for debugging purposes\n";
|
||||
|
||||
static char qsig_debug_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " qsig debug\n"
|
||||
" Enables dumping of QSIG facilities for debugging purposes\n";
|
||||
|
||||
static char qsig_no_debug_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " qsig no debug\n"
|
||||
" Disables dumping of QSIG facilities for debugging purposes\n";
|
||||
|
||||
static char show_exec_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " info\n"
|
||||
" Exec chancapi command on selected interface (exec interface command parameters).\n";
|
||||
|
||||
static char show_chat_manage_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " chat manage\n"
|
||||
" Manage chat conference (chat manage room member command parameters).\n";
|
||||
|
||||
#ifndef CC_AST_HAS_VERSION_1_6
|
||||
static
|
||||
#endif
|
||||
char chatinfo_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " chatinfo\n"
|
||||
" Show info about chat status.\n";
|
||||
|
||||
#define CC_CLI_TEXT_INFO "Show " CC_MESSAGE_BIGNAME " info"
|
||||
#define CC_CLI_TEXT_SHOW_CHANNELS "Show B-channel info"
|
||||
#define CC_CLI_TEXT_DEBUG "Enable " CC_MESSAGE_BIGNAME " debugging"
|
||||
#define CC_CLI_TEXT_NO_DEBUG "Disable " CC_MESSAGE_BIGNAME " debugging"
|
||||
#define CC_CLI_TEXT_QSIG_DEBUG "Enable QSIG debugging"
|
||||
#define CC_CLI_TEXT_QSIG_NO_DEBUG "Disable QSIG debugging"
|
||||
#define CC_CLI_TEXT_CHATINFO "Show " CC_MESSAGE_BIGNAME " chat info"
|
||||
#define CC_CLI_TEXT_SHOW_RESOURCES "Show used resources"
|
||||
#define CC_CLI_TEXT_SHOW_BRIDGES "Show used conference bridges"
|
||||
#define CC_CLI_TEXT_EXEC_CAPICOMMAND "Exec command"
|
||||
#define CC_CLI_TEXT_CHAT_MANAGE "Manager chat conference"
|
||||
|
||||
/*
|
||||
* helper functions to convert conf value to string
|
||||
*/
|
||||
static char *show_bproto(int bproto)
|
||||
{
|
||||
switch(bproto) {
|
||||
case CC_BPROTO_TRANSPARENT:
|
||||
return "trans";
|
||||
case CC_BPROTO_FAXG3:
|
||||
case CC_BPROTO_FAX3_BASIC:
|
||||
return " fax ";
|
||||
case CC_BPROTO_RTP:
|
||||
return " rtp ";
|
||||
case CC_BPROTO_VOCODER:
|
||||
return " vocoder ";
|
||||
}
|
||||
return " ??? ";
|
||||
}
|
||||
|
||||
static char *show_state(int state)
|
||||
{
|
||||
switch(state) {
|
||||
case CAPI_STATE_ALERTING:
|
||||
return "Ring ";
|
||||
case CAPI_STATE_CONNECTED:
|
||||
return "Conn ";
|
||||
case CAPI_STATE_DISCONNECTING:
|
||||
return "discP";
|
||||
case CAPI_STATE_DISCONNECTED:
|
||||
return "Disc ";
|
||||
case CAPI_STATE_CONNECTPENDING:
|
||||
return "Dial ";
|
||||
case CAPI_STATE_ANSWERING:
|
||||
return "Answ ";
|
||||
case CAPI_STATE_DID:
|
||||
return "DIDin";
|
||||
case CAPI_STATE_INCALL:
|
||||
return "icall";
|
||||
case CAPI_STATE_ONHOLD:
|
||||
return "Hold ";
|
||||
}
|
||||
return "-----";
|
||||
}
|
||||
|
||||
static char *show_isdnstate(unsigned int isdnstate, char *str)
|
||||
{
|
||||
str[0] = '\0';
|
||||
|
||||
if (isdnstate & CAPI_ISDN_STATE_PBX)
|
||||
strcat(str, "*");
|
||||
if (isdnstate & CAPI_ISDN_STATE_LI)
|
||||
strcat(str, "G");
|
||||
if (isdnstate & CAPI_ISDN_STATE_B3_UP)
|
||||
strcat(str, "B");
|
||||
if (isdnstate & CAPI_ISDN_STATE_B3_PEND)
|
||||
strcat(str, "b");
|
||||
if (isdnstate & CAPI_ISDN_STATE_PROGRESS)
|
||||
strcat(str, "P");
|
||||
if (isdnstate & CAPI_ISDN_STATE_HOLD)
|
||||
strcat(str, "H");
|
||||
if (isdnstate & CAPI_ISDN_STATE_ECT)
|
||||
strcat(str, "T");
|
||||
if (isdnstate & CAPI_ISDN_STATE_3PTY)
|
||||
strcat(str, "3");
|
||||
if (isdnstate & (CAPI_ISDN_STATE_SETUP | CAPI_ISDN_STATE_SETUP_ACK))
|
||||
strcat(str, "S");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* do command capi show channels
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_show_channels(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
struct capi_pvt *i;
|
||||
char iochar;
|
||||
char i_state[80];
|
||||
char b3q[32];
|
||||
int required_args;
|
||||
int provided_args;
|
||||
const char* required_channel_name = NULL;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " show channels";
|
||||
e->usage = show_channels_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
required_args = e->args;
|
||||
provided_args = a->argc;
|
||||
if (required_args < provided_args) {
|
||||
required_channel_name = a->argv[required_args];
|
||||
}
|
||||
#else
|
||||
required_args = 3;
|
||||
provided_args = argc;
|
||||
if (required_args < provided_args) {
|
||||
required_channel_name = argv[required_args];
|
||||
}
|
||||
#endif
|
||||
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " B-channel information:\n");
|
||||
ast_cli(fd, "Line-Name NTmode state i/o bproto isdnstate ton number\n");
|
||||
ast_cli(fd, "----------------------------------------------------------------\n");
|
||||
|
||||
pbx_capi_lock_interfaces();
|
||||
|
||||
for (i = capi_iflist; i; i = i->next) {
|
||||
if (i->channeltype != CAPI_CHANNELTYPE_B)
|
||||
continue;
|
||||
if ((required_channel_name != NULL) && (strcmp(required_channel_name, i->vname) != 0))
|
||||
continue;
|
||||
|
||||
if ((i->state == 0) || (i->state == CAPI_STATE_DISCONNECTED))
|
||||
iochar = '-';
|
||||
else if (i->outgoing)
|
||||
iochar = 'O';
|
||||
else
|
||||
iochar = 'I';
|
||||
|
||||
if (capidebug) {
|
||||
snprintf(b3q, sizeof(b3q), " B3q=%d B3count=%d",
|
||||
i->B3q, i->B3count);
|
||||
} else {
|
||||
b3q[0] = '\0';
|
||||
}
|
||||
|
||||
ast_cli(fd,
|
||||
"%-16s %s %s %c %s %-10s 0x%02x '%s'->'%s'%s\n",
|
||||
i->vname,
|
||||
i->ntmode ? "yes":"no ",
|
||||
show_state(i->state),
|
||||
iochar,
|
||||
show_bproto(i->bproto),
|
||||
show_isdnstate(i->isdnstate, i_state),
|
||||
i->cid_ton,
|
||||
i->cid,
|
||||
i->dnid,
|
||||
b3q
|
||||
);
|
||||
}
|
||||
|
||||
pbx_capi_unlock_interfaces();
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* do command capi show resources
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_show_resources(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_show_resources(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int ifc_type;
|
||||
const struct capi_pvt *i;
|
||||
int required_args;
|
||||
int provided_args;
|
||||
const char* required_channel_name = NULL;
|
||||
struct {
|
||||
const struct capi_pvt *head;
|
||||
void (*lock_proc)(void);
|
||||
void (*unlock_proc)(void);
|
||||
} data[2];
|
||||
|
||||
data[0].head = capi_iflist;
|
||||
data[0].lock_proc = pbx_capi_lock_interfaces;
|
||||
data[0].unlock_proc = pbx_capi_unlock_interfaces;
|
||||
data[1].head = pbx_capi_get_nulliflist();
|
||||
data[1].lock_proc = pbx_capi_nulliflist_lock;
|
||||
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " show resources";
|
||||
e->usage = show_resources_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
required_args = e->args;
|
||||
provided_args = a->argc;
|
||||
if (required_args < provided_args) {
|
||||
required_channel_name = a->argv[required_args];
|
||||
}
|
||||
#else
|
||||
required_args = 3;
|
||||
provided_args = argc;
|
||||
if (required_args < provided_args) {
|
||||
required_channel_name = argv[required_args];
|
||||
}
|
||||
#endif
|
||||
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " resources in use:\n");
|
||||
ast_cli(fd, "%-40s %-6s %-4s %-10s %-9s %-5s %-5s %-6s %-6s %-6s %-7s\n",
|
||||
"Line-Name", "Domain", "DTMF", "EchoCancel", "NoiseSupp", "RxAGC", "TxAGC", "RxGain", "TxGain", "CAPI", "Queue");
|
||||
ast_cli(fd, "-----------------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
|
||||
data[ifc_type].lock_proc();
|
||||
|
||||
for (i = data[ifc_type].head; i; i = i->next) {
|
||||
unsigned int queueDepth = 0;
|
||||
char* name;
|
||||
|
||||
if (((i->used == 0) && (i->channeltype != CAPI_CHANNELTYPE_NULL)) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
|
||||
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
|
||||
continue;
|
||||
if (i->data_plci != 0)
|
||||
continue;
|
||||
|
||||
name = ast_strdup(i->vname);
|
||||
if ((i->channeltype == CAPI_CHANNELTYPE_NULL) && (name != NULL)) {
|
||||
char* p = strstr(name, "-DATAPLCI");
|
||||
if (p != NULL)
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
if ((required_channel_name != NULL) &&
|
||||
(strcmp(required_channel_name, (name == 0) ? i->vname : name) != 0)) {
|
||||
ast_free(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DIVA_STREAMING
|
||||
queueDepth = capi_DivaStreamingGetStreamInUse(i->line_plci == NULL ? i : i->line_plci);
|
||||
#endif
|
||||
|
||||
ast_cli(fd, "%-40s %-6s %-4s %-10s %-9s %-5s %-5s %-.1f%-3s %-.1f%-3s%5d %7u\n",
|
||||
(name == 0) ? i->vname : name,
|
||||
(i->channeltype == CAPI_CHANNELTYPE_B) ? "TDM" : "IP",
|
||||
(i->isdnstate & CAPI_ISDN_STATE_DTMF) ? "Y" : "N",
|
||||
(i->isdnstate & CAPI_ISDN_STATE_EC) ? "Y" : "N",
|
||||
(i->divaAudioFlags & 0x0080) ? "Y" : "N", /* Noise supression */
|
||||
(i->divaAudioFlags & 0x0008) ? "Y" : "N", /* Rx AGC */
|
||||
(i->divaAudioFlags & 0x0004) ? "Y" : "N", /* Tx AGC */
|
||||
i->divaDigitalRxGainDB, "dB",
|
||||
i->divaDigitalTxGainDB, "dB",
|
||||
i->controller,
|
||||
queueDepth);
|
||||
ast_free (name);
|
||||
}
|
||||
|
||||
data[ifc_type].unlock_proc();
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* do command capi show bridges
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_show_bridges(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_show_bridges(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
const struct capichat_s *capiChatRoom;
|
||||
int required_args;
|
||||
int provided_args;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " show bridges";
|
||||
e->usage = show_bridges_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
required_args = e->args;
|
||||
provided_args = a->argc;
|
||||
#else
|
||||
required_args = 3;
|
||||
provided_args = argc;
|
||||
#endif
|
||||
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " conference bridges in use:\n");
|
||||
ast_cli(fd, "%-17s %-5s %-7s %-4s %-11s\n",
|
||||
"Bridge", "Group", "Members", "CAPI", "Queue depth");
|
||||
ast_cli(fd, "----------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
pbx_capi_lock_chat_rooms();
|
||||
for (capiChatRoom = pbx_capi_chat_get_room_c(NULL);
|
||||
capiChatRoom != NULL;
|
||||
capiChatRoom = pbx_capi_chat_get_room_c(capiChatRoom)) {
|
||||
const struct capi_pvt* i = pbx_capi_chat_get_room_interface_c(capiChatRoom);
|
||||
|
||||
if ((i->virtualBridgePeer == 0) || (i->bridgePeer == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned int groupNumber = pbx_capi_chat_get_room_group (capiChatRoom);
|
||||
if (groupNumber > 0) {
|
||||
const char* roomName = pbx_capi_chat_get_room_name(capiChatRoom);
|
||||
unsigned int groupNumber = pbx_capi_chat_get_room_group(capiChatRoom);
|
||||
unsigned int groupUsers = pbx_capi_chat_get_room_group_members(capiChatRoom);
|
||||
unsigned int queueDepth = 0;
|
||||
|
||||
#ifdef DIVA_STREAMING
|
||||
queueDepth = capi_DivaStreamingGetStreamInUse(i);
|
||||
#endif
|
||||
|
||||
ast_cli(fd, "%-17s %5u %7u %4d %11d\n",
|
||||
roomName, groupNumber, groupUsers, i->controller, queueDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
pbx_capi_unlock_chat_rooms();
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* do command capi info
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_info(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int i = 0, capi_num_controllers = pbx_capi_get_num_controllers();
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " info";
|
||||
e->usage = info_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
ast_cli(fd, "%s www.chan-capi.org\n", pbx_capi_get_module_description());
|
||||
|
||||
for (i = 1; i <= capi_num_controllers; i++) {
|
||||
const struct cc_capi_controller *capiController = pbx_capi_get_controller(i);
|
||||
if (capiController != NULL) {
|
||||
ast_cli(fd, "Contr%d: %d B channels total, %d B channels free.%s\n",
|
||||
i, capiController->nbchannels,
|
||||
capiController->nfreebchannels,
|
||||
(capiController->used) ? "":" (unused)");
|
||||
}
|
||||
}
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* enable debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_do_debug(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " debug";
|
||||
e->usage = debug_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
capidebug = 1;
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Debugging Enabled\n");
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* disable debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_no_debug(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " no debug";
|
||||
e->usage = no_debug_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
capidebug = 0;
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Debugging Disabled\n");
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* enable QSIG debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_qsig_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_qsig_do_debug(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " qsig debug";
|
||||
e->usage = qsig_debug_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
capiqsigdebug = 1;
|
||||
ast_cli(fd, "QSIG Debugging Enabled\n");
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* disable QSIG debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_qsig_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_qsig_no_debug(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " qsig no debug";
|
||||
e->usage = qsig_no_debug_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 4)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
capiqsigdebug = 0;
|
||||
ast_cli(fd, "QSIG Debugging Disabled\n");
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* exec capi command
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_exec_capicommand(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_exec_capicommand(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int required_args = 4;
|
||||
int provided_args;
|
||||
const char* requiredChannelName = NULL;
|
||||
const char* chancapiCommand = NULL;
|
||||
int ret;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " exec";
|
||||
e->usage = show_exec_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE) {
|
||||
return NULL;
|
||||
}
|
||||
provided_args = a->argc;
|
||||
if (provided_args < required_args) {
|
||||
return CLI_SHOWUSAGE;
|
||||
}
|
||||
requiredChannelName = a->argv[2];
|
||||
chancapiCommand = a->argv[3];
|
||||
#else
|
||||
provided_args = argc;
|
||||
if (provided_args < required_args) {
|
||||
return RESULT_SHOWUSAGE;
|
||||
}
|
||||
requiredChannelName = argv[2];
|
||||
chancapiCommand = argv[3];
|
||||
#endif
|
||||
|
||||
ret = pbx_capi_management_capicommand(requiredChannelName, chancapiCommand);
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
|
||||
#else
|
||||
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* exec capi command
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static char *pbxcli_capi_chat_manage_capicommand(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
static int pbxcli_capi_chat_manage_capicommand(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int required_args = 6;
|
||||
int provided_args;
|
||||
const char* roomName = NULL;
|
||||
const char* memberName = NULL;
|
||||
const char* chatCommand = NULL;
|
||||
const char* commandParameters = NULL;
|
||||
#ifdef CC_AST_HAS_VERSION_1_8
|
||||
const char * const *cli_argv;
|
||||
#elif (defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
|
||||
char **cli_argv;
|
||||
#else
|
||||
char * const *cli_argv;
|
||||
#endif
|
||||
int ret = -1;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " chat manage";
|
||||
e->usage = show_chat_manage_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE) {
|
||||
return NULL;
|
||||
}
|
||||
provided_args = a->argc;
|
||||
cli_argv = a->argv;
|
||||
if (provided_args < required_args) {
|
||||
return CLI_SHOWUSAGE;
|
||||
}
|
||||
#else
|
||||
provided_args = argc;
|
||||
cli_argv = argv;
|
||||
if (provided_args < required_args) {
|
||||
return RESULT_SHOWUSAGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
roomName = cli_argv[3];
|
||||
memberName = cli_argv[4];
|
||||
chatCommand = cli_argv[5];
|
||||
if (provided_args > required_args)
|
||||
commandParameters = cli_argv[6];
|
||||
|
||||
if (strcmp(chatCommand, "remove") == 0) {
|
||||
ret = pbx_capi_chat_remove_user (roomName, memberName);
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
|
||||
#else
|
||||
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* define commands
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static struct ast_cli_entry cc_cli_cmd[] = {
|
||||
AST_CLI_DEFINE(pbxcli_capi_info, CC_CLI_TEXT_INFO),
|
||||
AST_CLI_DEFINE(pbxcli_capi_show_channels, CC_CLI_TEXT_SHOW_CHANNELS),
|
||||
AST_CLI_DEFINE(pbxcli_capi_do_debug, CC_CLI_TEXT_DEBUG),
|
||||
AST_CLI_DEFINE(pbxcli_capi_no_debug, CC_CLI_TEXT_NO_DEBUG),
|
||||
AST_CLI_DEFINE(pbxcli_capi_qsig_do_debug, CC_CLI_TEXT_QSIG_DEBUG),
|
||||
AST_CLI_DEFINE(pbxcli_capi_qsig_no_debug, CC_CLI_TEXT_QSIG_NO_DEBUG),
|
||||
AST_CLI_DEFINE(pbxcli_capi_chatinfo, CC_CLI_TEXT_CHATINFO),
|
||||
#ifdef DIVA_STATUS
|
||||
AST_CLI_DEFINE(pbxcli_capi_ifc_status, CC_CLI_TEXT_IFC_STATUSINFO),
|
||||
#endif
|
||||
#ifdef DIVA_VERBOSE
|
||||
AST_CLI_DEFINE(pbxcli_capi_do_verbose, CC_CLI_TEXT_CAPI_DO_VERBOSE),
|
||||
AST_CLI_DEFINE(pbxcli_capi_no_verbose, CC_CLI_TEXT_CAPI_NO_VERBOSE),
|
||||
#endif
|
||||
AST_CLI_DEFINE(pbxcli_capi_show_resources, CC_CLI_TEXT_SHOW_RESOURCES),
|
||||
AST_CLI_DEFINE(pbxcli_capi_exec_capicommand, CC_CLI_TEXT_EXEC_CAPICOMMAND),
|
||||
AST_CLI_DEFINE(pbxcli_capi_chat_manage_capicommand, CC_CLI_TEXT_CHAT_MANAGE),
|
||||
AST_CLI_DEFINE(pbxcli_capi_show_bridges, CC_CLI_TEXT_SHOW_BRIDGES),
|
||||
};
|
||||
#else
|
||||
static struct ast_cli_entry cli_info =
|
||||
{ { CC_MESSAGE_NAME, "info", NULL }, pbxcli_capi_info, CC_CLI_TEXT_INFO, info_usage };
|
||||
static struct ast_cli_entry cli_show_channels =
|
||||
{ { CC_MESSAGE_NAME, "show", "channels", NULL }, pbxcli_capi_show_channels, CC_CLI_TEXT_SHOW_CHANNELS, show_channels_usage };
|
||||
static struct ast_cli_entry cli_debug =
|
||||
{ { CC_MESSAGE_NAME, "debug", NULL }, pbxcli_capi_do_debug, CC_CLI_TEXT_DEBUG, debug_usage };
|
||||
static struct ast_cli_entry cli_no_debug =
|
||||
{ { CC_MESSAGE_NAME, "no", "debug", NULL }, pbxcli_capi_no_debug, CC_CLI_TEXT_NO_DEBUG, no_debug_usage };
|
||||
static struct ast_cli_entry cli_qsig_debug =
|
||||
{ { CC_MESSAGE_NAME, "qsig", "debug", NULL }, pbxcli_capi_qsig_do_debug, CC_CLI_TEXT_QSIG_DEBUG, qsig_debug_usage };
|
||||
static struct ast_cli_entry cli_qsig_no_debug =
|
||||
{ { CC_MESSAGE_NAME, "qsig", "no", "debug", NULL }, pbxcli_capi_qsig_no_debug, CC_CLI_TEXT_QSIG_NO_DEBUG, qsig_no_debug_usage };
|
||||
static struct ast_cli_entry cli_chatinfo =
|
||||
{ { CC_MESSAGE_NAME, "chatinfo", NULL }, pbxcli_capi_chatinfo, CC_CLI_TEXT_CHATINFO, chatinfo_usage };
|
||||
#ifdef DIVA_STATUS
|
||||
static struct ast_cli_entry cli_ifcstate =
|
||||
{ { CC_MESSAGE_NAME, "ifcstate", NULL }, pbxcli_capi_ifc_status, CC_CLI_TEXT_IFC_STATUSINFO, diva_status_ifc_state_usage };
|
||||
#endif
|
||||
#ifdef DIVA_VERBOSE
|
||||
static struct ast_cli_entry cli_verbose =
|
||||
{ { CC_MESSAGE_NAME, "verbose", NULL }, pbxcli_capi_do_verbose, CC_CLI_TEXT_CAPI_DO_VERBOSE, capi_do_verbose_usage };
|
||||
static struct ast_cli_entry cli_no_verbose =
|
||||
{ { CC_MESSAGE_NAME, "no", "verbose", NULL }, pbxcli_capi_no_verbose, CC_CLI_TEXT_CAPI_NO_VERBOSE, capi_no_verbose_usage };
|
||||
#endif
|
||||
static struct ast_cli_entry cli_show_resources =
|
||||
{ { CC_MESSAGE_NAME, "show", "resources", NULL }, pbxcli_capi_show_resources, CC_CLI_TEXT_SHOW_RESOURCES, show_resources_usage };
|
||||
static struct ast_cli_entry cli_exec_capicommand =
|
||||
{ { CC_MESSAGE_NAME, "exec", NULL }, pbxcli_capi_exec_capicommand, CC_CLI_TEXT_CHAT_MANAGE, show_exec_usage };
|
||||
static struct ast_cli_entry cli_chat_manage =
|
||||
{ { CC_MESSAGE_NAME, "chat", "manage", NULL }, pbxcli_capi_chat_manage_capicommand, CC_CLI_TEXT_EXEC_CAPICOMMAND, show_chat_manage_usage };
|
||||
static struct ast_cli_entry cli_show_bridges =
|
||||
{ { CC_MESSAGE_NAME, "show", "bridges", NULL }, pbxcli_capi_show_bridges, CC_CLI_TEXT_SHOW_BRIDGES, show_bridges_usage };
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void pbx_capi_cli_register(void)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
ast_cli_register_multiple(cc_cli_cmd, sizeof(cc_cli_cmd)/ sizeof(struct ast_cli_entry));
|
||||
#else
|
||||
ast_cli_register(&cli_info);
|
||||
ast_cli_register(&cli_show_channels);
|
||||
ast_cli_register(&cli_debug);
|
||||
ast_cli_register(&cli_no_debug);
|
||||
ast_cli_register(&cli_qsig_debug);
|
||||
ast_cli_register(&cli_qsig_no_debug);
|
||||
ast_cli_register(&cli_chatinfo);
|
||||
#ifdef DIVA_STATUS
|
||||
ast_cli_register(&cli_ifcstate);
|
||||
#endif
|
||||
#ifdef DIVA_VERBOSE
|
||||
ast_cli_register(&cli_verbose);
|
||||
ast_cli_register(&cli_no_verbose);
|
||||
#endif
|
||||
ast_cli_register(&cli_show_resources);
|
||||
ast_cli_register(&cli_exec_capicommand);
|
||||
ast_cli_register(&cli_chat_manage);
|
||||
ast_cli_register(&cli_show_bridges);
|
||||
#endif
|
||||
}
|
||||
|
||||
void pbx_capi_cli_unregister(void)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
ast_cli_unregister_multiple(cc_cli_cmd, sizeof(cc_cli_cmd)/ sizeof(struct ast_cli_entry));
|
||||
#else
|
||||
ast_cli_unregister(&cli_info);
|
||||
ast_cli_unregister(&cli_show_channels);
|
||||
ast_cli_unregister(&cli_debug);
|
||||
ast_cli_unregister(&cli_no_debug);
|
||||
ast_cli_unregister(&cli_qsig_debug);
|
||||
ast_cli_unregister(&cli_qsig_no_debug);
|
||||
ast_cli_unregister(&cli_chatinfo);
|
||||
#ifdef DIVA_STATUS
|
||||
ast_cli_unregister(&cli_ifcstate);
|
||||
#endif
|
||||
#ifdef DIVA_VERBOSE
|
||||
ast_cli_unregister(&cli_verbose);
|
||||
ast_cli_unregister(&cli_no_verbose);
|
||||
#endif
|
||||
ast_cli_unregister(&cli_show_resources);
|
||||
ast_cli_unregister(&cli_exec_capicommand);
|
||||
ast_cli_unregister(&cli_chat_manage);
|
||||
ast_cli_unregister(&cli_show_bridges);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2010 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* Reworked, but based on the work of
|
||||
* Copyright (C) 2002-2005 Junghanns.NET GmbH
|
||||
*
|
||||
* Klaus-Peter Junghanns <kapejod@ns1.jnetdns.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
#ifndef __CC_CLI_IFC_H__
|
||||
#define __CC_CLI_IFC_H__
|
||||
|
||||
void pbx_capi_cli_register(void);
|
||||
void pbx_capi_cli_unregister(void);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic, 2009.
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Dialogic range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
#include <sys/signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "xlaw.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_rtp.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_qsig_ecma.h"
|
||||
#include "chan_capi_qsig_asn197ade.h"
|
||||
#include "chan_capi_qsig_asn197no.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_supplementary.h"
|
||||
#include "chan_capi_chat.h"
|
||||
#include "chan_capi_command.h"
|
||||
|
||||
typedef struct _pbx_capi_voice_command {
|
||||
diva_entity_link_t link;
|
||||
pbx_capi_command_proc_t pbx_capi_command;
|
||||
char channel_command_digits[AST_MAX_EXTENSION+1];
|
||||
int length; /* channel_command_digits length */
|
||||
char command_name[64];
|
||||
char command_parameters[128];
|
||||
} pbx_capi_voice_command_t;
|
||||
|
||||
/*
|
||||
* LOCALS
|
||||
*/
|
||||
static const char* pbx_capi_voicecommand_digits = "1234567890ABCD*#";
|
||||
static int pbx_capi_command_nop(struct ast_channel *c, char *param);
|
||||
static pbx_capi_voice_command_t* pbx_capi_find_command(struct capi_pvt *i, const char* name);
|
||||
static pbx_capi_voice_command_t* pbx_capi_find_command_by_key(struct capi_pvt *i, const char* key);
|
||||
static pbx_capi_voice_command_t* pbx_capi_voicecommand_find_digit_command(diva_entity_queue_t* q, const char* digits, int length, int* info);
|
||||
static void pbx_capi_voicecommand_insert_command(diva_entity_queue_t* q, pbx_capi_voice_command_t* cmd);
|
||||
|
||||
|
||||
/*
|
||||
* voicecommand|key|param1|param2|...
|
||||
*
|
||||
*/
|
||||
int pbx_capi_voicecommand(struct ast_channel *c, char *param)
|
||||
{
|
||||
struct capi_pvt *i;
|
||||
pbx_capi_voice_command_t* cmd;
|
||||
const char* command[2];
|
||||
const char* key[2];
|
||||
size_t length;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const struct ast_channel_tech *cur_tech = ast_channel_tech(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const struct ast_channel_tech *cur_tech = c->tech;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
|
||||
if (cur_tech == &capi_tech) {
|
||||
i = CC_CHANNEL_PVT(c);
|
||||
} else {
|
||||
i = pbx_check_resource_plci(c);
|
||||
}
|
||||
if (i == 0) {
|
||||
/*
|
||||
Ignore command silently to ensure same context can be used to process
|
||||
all types of calls or in case of fallback to NULL PLCI
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((param == NULL) || (*param == 0)) { /* Remove all voice commands */
|
||||
cc_mutex_lock(&i->lock);
|
||||
pbx_capi_voicecommand_cleanup(i);
|
||||
cc_mutex_unlock(&i->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
command[0] = param;
|
||||
command[1] = strchr(command[0], '|');
|
||||
|
||||
if (command[1] == 0) {
|
||||
/*
|
||||
* Remove command
|
||||
*/
|
||||
cc_mutex_lock(&i->lock);
|
||||
while ((cmd = pbx_capi_find_command(i, command[0])) != 0) {
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_4"%s: voicecommand:%s removed\n",
|
||||
i->vname, cmd->command_name);
|
||||
diva_q_remove(&i->channel_command_q, &cmd->link);
|
||||
ast_free (cmd);
|
||||
}
|
||||
cc_mutex_unlock(&i->lock);
|
||||
} else {
|
||||
if ((command[1] - command[0]) < 2 || (command[1] - command[0]) >= sizeof(cmd->command_name) ||
|
||||
strchr(pbx_capi_voicecommand_digits, command[1][1]) == 0) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME" voicecommand requires an argument im format 'voicecommand[|key[|param1|param2|...]]'\n");
|
||||
return -1;
|
||||
}
|
||||
key[0] = &command[1][1];
|
||||
key[1] = strchr (key[0], '|');
|
||||
length = 0;
|
||||
if ((key[1] == 0 && strlen(key[0]) >= sizeof(cmd->channel_command_digits)) ||
|
||||
(key[1] != 0 && ((key[1] - key[0]) == 0 || (key[1] - key[0]) >= sizeof(cmd->channel_command_digits) ||
|
||||
key[1][1] == 0 || (length = strlen (&key[1][1])) >= sizeof(cmd->command_parameters)))) {
|
||||
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME
|
||||
" voicecommand requires an argument im format 'voicecommand[|key[|param1|param2|...]]'\n");
|
||||
return -1;
|
||||
}
|
||||
if (key[1] == 0) {
|
||||
key[1] = key[0] + strlen(key[0]);
|
||||
length = 0;
|
||||
}
|
||||
|
||||
{
|
||||
const char* p = key[0];
|
||||
|
||||
for (p = key[0]; p < key[1]; p++) {
|
||||
if (strchr(pbx_capi_voicecommand_digits, *p) == 0) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME
|
||||
" voicecommand key can use only '%s'\n", pbx_capi_voicecommand_digits);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmd = ast_malloc(sizeof(*cmd));
|
||||
if (cmd == NULL) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME " can not allocate memory for voice command\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy (cmd->command_parameters, &key[1][1], length);
|
||||
cmd->command_parameters[length] = 0;
|
||||
|
||||
length = command[1] - command[0];
|
||||
memcpy (cmd->command_name, command[0], length);
|
||||
cmd->command_name[length] = 0;
|
||||
|
||||
length = key[1] - key[0];
|
||||
memcpy (cmd->channel_command_digits, key[0], length);
|
||||
cmd->channel_command_digits[length] = 0;
|
||||
cmd->length = length;
|
||||
|
||||
cmd->pbx_capi_command = pbx_capi_lockup_command_by_name(cmd->command_name);
|
||||
if ( cmd->pbx_capi_command == 0) {
|
||||
cmd->pbx_capi_command = pbx_capi_command_nop; /* accept unknown commands for compatibility reason */
|
||||
}
|
||||
|
||||
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_4 "%s: %svoicecommand:%s|%s|%s\n",
|
||||
i->vname, (cmd->pbx_capi_command == pbx_capi_command_nop) ? "dummy " : "",
|
||||
cmd->command_name, cmd->channel_command_digits, cmd->command_parameters);
|
||||
|
||||
{
|
||||
pbx_capi_voice_command_t* present_cmd;
|
||||
|
||||
cc_mutex_lock(&i->lock);
|
||||
if ((present_cmd = pbx_capi_find_command_by_key(i, cmd->command_name)) != 0) {
|
||||
diva_q_remove(&i->channel_command_q, &present_cmd->link);
|
||||
}
|
||||
pbx_capi_voicecommand_insert_command(&i->channel_command_q, cmd);
|
||||
cc_mutex_unlock(&i->lock);
|
||||
|
||||
if (present_cmd != 0) {
|
||||
ast_free (present_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pbx_capi_voicecommand_transparency(struct ast_channel *c, char *param)
|
||||
{
|
||||
struct capi_pvt *i;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const struct ast_channel_tech *cur_tech = ast_channel_tech(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const struct ast_channel_tech *cur_tech = c->tech;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
|
||||
if (cur_tech == &capi_tech) {
|
||||
i = CC_CHANNEL_PVT(c);
|
||||
} else {
|
||||
i = pbx_check_resource_plci(c);
|
||||
}
|
||||
if (i == 0) {
|
||||
/*
|
||||
Ignore command silently to ensure same context can be used to process
|
||||
all types of calls or in case of fallback to NULL PLCI
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((param == NULL) || (*param == 0)) {
|
||||
cc_log(LOG_WARNING, "Parameter for voicecommand transparency missing.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_true(param)) {
|
||||
i->command_pass_digits = 1;
|
||||
} else if (ast_false(param)) {
|
||||
i->command_pass_digits = 0;
|
||||
} else {
|
||||
cc_log(LOG_WARNING, "Wrong parameter for voicecommand transparency.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pbx_capi_voicecommand_cleanup(struct capi_pvt *i)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
while ((link = diva_q_get_head(&i->channel_command_q)) != NULL) {
|
||||
diva_q_remove(&i->channel_command_q, link);
|
||||
ast_free(link);
|
||||
}
|
||||
|
||||
i->channel_command_digit = 0;
|
||||
i->channel_command_timestamp = 0;
|
||||
i->command_pass_digits = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pbx_capi_voice_command_t* pbx_capi_find_command(struct capi_pvt *i, const char* name)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head (&i->channel_command_q); link != 0; link = diva_q_get_next(link)) {
|
||||
if (strcmp(((pbx_capi_voice_command_t*)link)->command_name, name) == 0) {
|
||||
return ((pbx_capi_voice_command_t*)link);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pbx_capi_voice_command_t* pbx_capi_find_command_by_key(struct capi_pvt *i, const char* key)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head (&i->channel_command_q); link != 0; link = diva_q_get_next(link)) {
|
||||
if (strcmp (((pbx_capi_voice_command_t*)link)->channel_command_digits, key) == 0) {
|
||||
return ((pbx_capi_voice_command_t*)link);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process received DTMF digit
|
||||
*
|
||||
* returs zero if digit should be processed as usually
|
||||
* returns -1 if digit should be discarded
|
||||
*/
|
||||
int pbx_capi_voicecommand_process_digit(struct capi_pvt *i, struct ast_channel *owner, char digit)
|
||||
{
|
||||
struct ast_channel *c = (owner == 0) ? i->owner : owner;
|
||||
pbx_capi_voice_command_t* cmd;
|
||||
int info;
|
||||
time_t t;
|
||||
|
||||
/*
|
||||
Simple algorithm due to low amount of entries, moreover all sequences will be short, only 1 ... 2 digits
|
||||
*/
|
||||
if ((c == NULL) || (diva_q_get_head(&i->channel_command_q) == 0) ||
|
||||
(strchr(pbx_capi_voicecommand_digits, digit) == 0)) {
|
||||
i->channel_command_digit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = time(0);
|
||||
if (((i->channel_command_digit != 0) && (difftime(t, i->channel_command_timestamp) > 2)) ||
|
||||
(i->channel_command_digit >= (sizeof(i->channel_command_digits) - 1))) {
|
||||
i->channel_command_digit = 0;
|
||||
}
|
||||
|
||||
i->channel_command_timestamp = t;
|
||||
|
||||
i->channel_command_digits[i->channel_command_digit++] = digit;
|
||||
i->channel_command_digits[i->channel_command_digit] = 0;
|
||||
cmd = pbx_capi_voicecommand_find_digit_command(
|
||||
&i->channel_command_q,
|
||||
i->channel_command_digits,
|
||||
i->channel_command_digit,
|
||||
&info);
|
||||
|
||||
if (cmd != 0) {
|
||||
char command_parameters_copy[sizeof( cmd->command_parameters)];
|
||||
|
||||
i->channel_command_digit = 0;
|
||||
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_4 "%s: call voicecommand:%s|%s|%s\n",
|
||||
i->vname, cmd->command_name, cmd->channel_command_digits, cmd->command_parameters);
|
||||
|
||||
strcpy (command_parameters_copy, cmd->command_parameters);
|
||||
info = ((*(cmd->pbx_capi_command))(c, command_parameters_copy));
|
||||
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_4 "%s: voicecommand:%s|%s|%s %s\n",
|
||||
i->vname, cmd->command_name, cmd->channel_command_digits, cmd->command_parameters, info == 0 ? "OK" : "ERROR");
|
||||
|
||||
} else if (info == 0) {
|
||||
i->channel_command_digit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((i->command_pass_digits != 0) ? 0 : -1);
|
||||
}
|
||||
|
||||
static pbx_capi_voice_command_t* pbx_capi_voicecommand_find_digit_command(
|
||||
diva_entity_queue_t* q,
|
||||
const char* digits,
|
||||
int length,
|
||||
int* info)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (*info = 0, link = diva_q_get_head(q);
|
||||
link != 0 && length <= ((pbx_capi_voice_command_t*)link)->length;
|
||||
link = diva_q_get_next (link)) {
|
||||
pbx_capi_voice_command_t* cmd = (pbx_capi_voice_command_t*)link;
|
||||
|
||||
if (memcmp(digits, cmd->channel_command_digits, length) == 0) {
|
||||
*info = 1;
|
||||
if (length == cmd->length) {
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pbx_capi_command_nop(struct ast_channel *c, char *param)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pbx_capi_voicecommand_insert_command(diva_entity_queue_t* q, pbx_capi_voice_command_t* cmd)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head (q); link != 0; link = diva_q_get_next (link)) {
|
||||
if (((pbx_capi_voice_command_t*)link)->length <= cmd->length) {
|
||||
diva_q_insert_before (q, link, &cmd->link);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
diva_q_add_tail(q, &cmd->link);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* vim:ts=2
|
||||
*/
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic, 2009.
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Dialogic range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __CHAN_CAPI_COMMAND_H__
|
||||
#define __CHAN_CAPI_COMMAND_H__
|
||||
|
||||
int pbx_capi_voicecommand (struct ast_channel *c, char *param);
|
||||
int pbx_capi_voicecommand_transparency (struct ast_channel *c, char *param);
|
||||
int pbx_capi_voicecommand_process_digit (struct capi_pvt *i, struct ast_channel *owner, char digit);
|
||||
int pbx_capi_voicecommand_cleanup (struct capi_pvt *i);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_chat.h"
|
||||
#include "chan_capi_devstate.h"
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
static
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
enum ast_device_state
|
||||
#else
|
||||
int
|
||||
#endif
|
||||
pbx_capi_chat_room_state(const char *data);
|
||||
|
||||
static int capiChatProviderRegistered;
|
||||
|
||||
void pbx_capi_register_device_state_providers(void)
|
||||
{
|
||||
int i, capi_num_controllers;
|
||||
|
||||
capiChatProviderRegistered = (ast_devstate_prov_add("Capichat", pbx_capi_chat_room_state) == 0);
|
||||
|
||||
/*
|
||||
Set initial device state for all supported interface
|
||||
*/
|
||||
for (i = 1, capi_num_controllers = pbx_capi_get_num_controllers();
|
||||
i <= capi_num_controllers;
|
||||
i++) {
|
||||
const struct cc_capi_controller *capiController = pbx_capi_get_controller(i);
|
||||
|
||||
if (capiController != NULL) {
|
||||
pbx_capi_ifc_state_event(capiController, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbx_capi_unregister_device_state_providers(void)
|
||||
{
|
||||
if (capiChatProviderRegistered != 0) {
|
||||
ast_devstate_prov_del("Capichat");
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Read conference room state
|
||||
*/
|
||||
static
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
enum ast_device_state
|
||||
#else
|
||||
int
|
||||
#endif
|
||||
pbx_capi_chat_room_state(const char *data)
|
||||
{
|
||||
const struct capichat_s *room;
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
enum ast_device_state ret = AST_DEVICE_NOT_INUSE;
|
||||
#else
|
||||
int ret = AST_DEVICE_NOT_INUSE;
|
||||
#endif
|
||||
|
||||
if (data == 0)
|
||||
return AST_DEVICE_INVALID;
|
||||
|
||||
pbx_capi_lock_chat_rooms();
|
||||
for (room = pbx_capi_chat_get_room_c(NULL);
|
||||
room != 0;
|
||||
room = pbx_capi_chat_get_room_c(room)) {
|
||||
if (strcmp(data, pbx_capi_chat_get_room_name(room)) == 0) {
|
||||
ret = AST_DEVICE_INUSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pbx_capi_unlock_chat_rooms();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Conference room state change
|
||||
*/
|
||||
void pbx_capi_chat_room_state_event(const char* roomName, int inUse)
|
||||
{
|
||||
if (capiChatProviderRegistered != 0) {
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
ast_devstate_changed((inUse != 0) ? AST_DEVICE_INUSE : AST_DEVICE_NOT_INUSE,
|
||||
#ifdef CC_AST_HAS_AST_DEVSTATE_CACHE
|
||||
AST_DEVSTATE_CACHABLE,
|
||||
#endif
|
||||
"capichat:%s", roomName);
|
||||
#else
|
||||
ast_device_state_changed("capichat:%s", roomName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void pbx_capi_ifc_state_event(const struct cc_capi_controller* capiController, int channelsChanged)
|
||||
{
|
||||
if ((channelsChanged == 0) ||
|
||||
(capiController->nbchannels == capiController->nfreebchannels) ||
|
||||
(capiController->nfreebchannels == 0) ||
|
||||
((capiController->nfreebchannels < capiController->nfreebchannelsHardThr) &&
|
||||
(capiController->nfreebchannels - channelsChanged >= capiController->nfreebchannelsHardThr)) ||
|
||||
((capiController->nfreebchannels >= capiController->nfreebchannelsHardThr) &&
|
||||
(capiController->nfreebchannels - channelsChanged < capiController->nfreebchannelsHardThr))) {
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
ast_devstate_changed(AST_DEVICE_UNKNOWN,
|
||||
#ifdef CC_AST_HAS_AST_DEVSTATE_CACHE
|
||||
AST_DEVSTATE_CACHABLE,
|
||||
#endif
|
||||
CC_MESSAGE_BIGNAME"/I%d/congestion", capiController->controller);
|
||||
#else
|
||||
ast_device_state_changed (CC_MESSAGE_BIGNAME"/I%d/congestion", capiController->controller);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __CC_DEVICE_STATE_PROVIDER_INTERFACE_H__
|
||||
#define __CC_DEVICE_STATE_PROVIDER_INTERFACE_H__
|
||||
|
||||
void pbx_capi_register_device_state_providers(void);
|
||||
void pbx_capi_unregister_device_state_providers(void);
|
||||
void pbx_capi_chat_room_state_event(const char* roomName, int inUse);
|
||||
void pbx_capi_ifc_state_event(const struct cc_capi_controller* capiController, int channelsChanged);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_10_0 /* { */
|
||||
|
||||
#define CC_FORMAT_ALAW (1ULL << 3)
|
||||
#define CC_FORMAT_G722 (1ULL << 12)
|
||||
#define CC_FORMAT_G723_1 (1ULL << 0)
|
||||
#define CC_FORMAT_G726 (1ULL << 11)
|
||||
#define CC_FORMAT_G729A (1ULL << 8)
|
||||
#define CC_FORMAT_GSM (1ULL << 1)
|
||||
#define CC_FORMAT_ILBC (1ULL << 10)
|
||||
#define CC_FORMAT_SIREN14 (1ULL << 14)
|
||||
#define CC_FORMAT_SIREN7 (1ULL << 13)
|
||||
#define CC_FORMAT_SLINEAR (1ULL << 6)
|
||||
#define CC_FORMAT_SLINEAR16 (1ULL << 15)
|
||||
#define CC_FORMAT_ULAW (1ULL << 2)
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
#include <asterisk/format_compatibility.h>
|
||||
#include <asterisk/format_cache.h>
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
static inline struct ast_format * ccCodec2AstCodec(int ccCodec)
|
||||
{
|
||||
return (ast_format_compatibility_bitfield2format(ccCodec));
|
||||
}
|
||||
#else
|
||||
static inline enum ast_format_id ccCodec2AstCodec(int ccCodec)
|
||||
{
|
||||
return (ast_format_id_from_old_bitfield(ccCodec));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline const char* cc_getformatname(int ccCodec)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * id = ccCodec2AstCodec (ccCodec);
|
||||
return ast_format_get_name(id);
|
||||
#else
|
||||
enum ast_format_id id = ccCodec2AstCodec (ccCodec);
|
||||
struct ast_format fmt;
|
||||
|
||||
ast_format_clear(&fmt);
|
||||
ast_format_set(&fmt, id, 0);
|
||||
|
||||
return ast_getformatname(&fmt);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void cc_add_formats(struct ast_format_cap *fmts, unsigned int divaFormats)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
unsigned int ccCodec = (1U << i);
|
||||
|
||||
if ((divaFormats & ccCodec) != 0) {
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * id = ccCodec2AstCodec (ccCodec);
|
||||
ast_format_cap_remove_by_type(fmts, AST_MEDIA_TYPE_AUDIO);
|
||||
ast_format_cap_append(fmts, id, 0);
|
||||
#else
|
||||
enum ast_format_id id = ccCodec2AstCodec (ccCodec);
|
||||
struct ast_format fmt;
|
||||
|
||||
ast_format_clear(&fmt);
|
||||
ast_format_set(&fmt, id, 0);
|
||||
ast_format_cap_add(fmts, &fmt);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int cc_set_best_codec(struct ast_channel *a)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * bestCodec;
|
||||
|
||||
bestCodec = ast_format_cap_get_format(ast_channel_nativeformats(a), 0);
|
||||
if (bestCodec == ast_format_none) {
|
||||
bestCodec = ast_format_alaw;
|
||||
}
|
||||
|
||||
ast_set_read_format(a, bestCodec);
|
||||
ast_set_write_format(a, bestCodec);
|
||||
|
||||
return (int)ast_format_compatibility_format2bitfield(bestCodec);
|
||||
#else
|
||||
struct ast_format bestCodec;
|
||||
|
||||
ast_format_clear(&bestCodec);
|
||||
|
||||
if (ast_best_codec(ast_channel_nativeformats(a), &bestCodec) == NULL) {
|
||||
/*
|
||||
Fallback to aLaw
|
||||
*/
|
||||
ast_format_set(&bestCodec, CC_FORMAT_ALAW, 0);
|
||||
}
|
||||
|
||||
ast_format_copy(ast_channel_readformat(a), &bestCodec);
|
||||
ast_format_copy(ast_channel_readformat(a), &bestCodec);
|
||||
ast_format_copy(ast_channel_rawwriteformat(a), &bestCodec);
|
||||
ast_format_copy(ast_channel_writeformat(a), &bestCodec);
|
||||
|
||||
return (int)ast_format_to_old_bitfield(&bestCodec);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void cc_set_read_format(struct ast_channel* a, int ccCodec)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * ccFmt;
|
||||
|
||||
ccFmt = ccCodec2AstCodec(ccCodec);
|
||||
|
||||
ast_set_read_format(a, ccFmt);
|
||||
#else
|
||||
struct ast_format ccFmt;
|
||||
|
||||
ast_format_clear(&ccFmt);
|
||||
ast_format_set(&ccFmt, ccCodec, 0);
|
||||
ast_set_read_format(a, &ccFmt);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void cc_set_write_format(struct ast_channel* a, int ccCodec)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * ccFmt;
|
||||
|
||||
ccFmt = ccCodec2AstCodec(ccCodec);
|
||||
|
||||
ast_set_write_format(a, ccFmt);
|
||||
#else
|
||||
struct ast_format ccFmt;
|
||||
|
||||
ast_format_clear(&ccFmt);
|
||||
ast_format_set(&ccFmt, ccCodec, 0);
|
||||
ast_set_write_format(a, &ccFmt);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
#define cc_parse_allow_disallow(__capability__, __value__, __allowing__, __cap__) do{\
|
||||
__capability__ = ast_format_cap_update_by_allow_disallow(__cap__, __value__, __allowing__);}while(0)
|
||||
|
||||
static inline uint64_t cc_get_formats_as_bits(const struct ast_format_cap *cap)
|
||||
{
|
||||
uint64_t bitfield = 0;
|
||||
int x;
|
||||
|
||||
for (x = 0; x < ast_format_cap_count(cap); x++) {
|
||||
struct ast_format *format = ast_format_cap_get_format(cap, x);
|
||||
bitfield |= ast_format_compatibility_format2bitfield(format);
|
||||
ao2_ref(format, -1);
|
||||
}
|
||||
|
||||
return bitfield;
|
||||
}
|
||||
|
||||
#else
|
||||
#define cc_parse_allow_disallow(__prefs__, __capability__, __value__, __allowing__, __cap__) do{\
|
||||
ast_parse_allow_disallow(__prefs__, __cap__, __value__, __allowing__); \
|
||||
*(__capability__) = (int)ast_format_cap_to_old_bitfield(__cap__); }while(0)
|
||||
|
||||
#define cc_get_formats_as_bits(__a__) (int)ast_format_cap_to_old_bitfield(__a__)
|
||||
#endif
|
||||
|
||||
static inline int cc_get_best_codec_as_bits(int src)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format_cap *dst;
|
||||
struct ast_format *bestCodec;
|
||||
int bit;
|
||||
|
||||
dst = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
|
||||
|
||||
for (bit = 0; bit < 64; ++bit) {
|
||||
uint64_t mask = (1ULL << bit);
|
||||
|
||||
if (mask & src) {
|
||||
struct ast_format *format;
|
||||
|
||||
format = ast_format_compatibility_bitfield2format(mask);
|
||||
ast_format_cap_remove_by_type(dst, AST_MEDIA_TYPE_AUDIO);
|
||||
if (format && ast_format_cap_append(dst, format, 0)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bestCodec = ast_format_cap_get_format(dst, 0);
|
||||
ao2_ref(dst, -1);
|
||||
|
||||
ret = (int)ast_format_compatibility_format2bitfield(bestCodec);
|
||||
#else
|
||||
struct ast_format_cap *dst = ast_format_cap_alloc_nolock();
|
||||
|
||||
if (dst != 0) {
|
||||
struct ast_format bestCodec;
|
||||
|
||||
ast_format_cap_from_old_bitfield(dst, src);
|
||||
ast_format_clear(&bestCodec);
|
||||
if (ast_best_codec(dst, &bestCodec) != NULL) {
|
||||
ret = (int)ast_format_to_old_bitfield(&bestCodec);
|
||||
}
|
||||
ast_format_cap_destroy(dst);
|
||||
}
|
||||
|
||||
#endif
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static inline int cc_getformatbyname(const char* value)
|
||||
{
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
struct ast_format * fmt;
|
||||
int ret = 0;
|
||||
|
||||
fmt = ast_format_cache_get(value);
|
||||
if (fmt) {
|
||||
ret = (int)ast_format_compatibility_format2bitfield(fmt);
|
||||
}
|
||||
#else
|
||||
struct ast_format fmt;
|
||||
int ret = 0;
|
||||
|
||||
if (ast_getformatbyname(value, &fmt) != NULL) {
|
||||
ret = (int)ast_format_to_old_bitfield(&fmt);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#else /* CC_AST_HAS_VERSION_10_0 */
|
||||
|
||||
#define CC_FORMAT_ALAW AST_FORMAT_ALAW
|
||||
#ifdef AST_FORMAT_G722
|
||||
#define CC_FORMAT_G722 AST_FORMAT_G722
|
||||
#endif
|
||||
#define CC_FORMAT_G723_1 AST_FORMAT_G723_1
|
||||
#define CC_FORMAT_G726 AST_FORMAT_G726
|
||||
#define CC_FORMAT_G729A AST_FORMAT_G729A
|
||||
#define CC_FORMAT_GSM AST_FORMAT_GSM
|
||||
#define CC_FORMAT_ILBC AST_FORMAT_ILBC
|
||||
#ifdef AST_FORMAT_SIREN14
|
||||
#define CC_FORMAT_SIREN14 AST_FORMAT_SIREN14
|
||||
#endif
|
||||
#ifdef AST_FORMAT_SIREN7
|
||||
#define CC_FORMAT_SIREN7 AST_FORMAT_SIREN7
|
||||
#endif
|
||||
#ifdef AST_FORMAT_SLINEAR
|
||||
#define CC_FORMAT_SLINEAR AST_FORMAT_SLINEAR
|
||||
#endif
|
||||
#ifdef AST_FORMAT_SLINEAR16
|
||||
#define CC_FORMAT_SLINEAR16 AST_FORMAT_SLINEAR16
|
||||
#endif
|
||||
#define CC_FORMAT_ULAW AST_FORMAT_ULAW
|
||||
|
||||
|
||||
#define cc_getformatname(__x__) ast_getformatname((__x__))
|
||||
#define cc_add_formats(__x__,__y__) do {(__x__)=(__y__);}while(0)
|
||||
|
||||
static inline int cc_set_best_codec(struct ast_channel *a)
|
||||
{
|
||||
int fmt = ast_best_codec(a->nativeformats);
|
||||
|
||||
a->readformat = fmt;
|
||||
a->writeformat = fmt;
|
||||
a->rawreadformat = fmt;
|
||||
a->rawwriteformat = fmt;
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
#define cc_set_read_format(__a__, __b__) ast_set_read_format(__a__, __b__)
|
||||
#define cc_set_write_format(__a__, __b__) ast_set_write_format(__a__, __b__)
|
||||
#define cc_parse_allow_disallow(__a__, __b__, __c__, __d__, __e__) ast_parse_allow_disallow(__a__, __b__, __c__, __d__)
|
||||
#define cc_get_formats_as_bits(__a__) (__a__)
|
||||
#define cc_get_best_codec_as_bits(__a__) ast_best_codec(__a__)
|
||||
#define cc_getformatbyname(__a__) ast_getformatbyname(__a__)
|
||||
#endif /* } */
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_chat.h"
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel);
|
||||
|
||||
/*!
|
||||
\brief Execute any capicommand
|
||||
|
||||
\note Called from CLI or from AMI context
|
||||
*/
|
||||
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand) {
|
||||
int ifc_type, retry_search, search_loops;
|
||||
struct capi_pvt *i;
|
||||
struct {
|
||||
struct capi_pvt *head;
|
||||
void (*lock_proc)(void);
|
||||
void (*unlock_proc)(void);
|
||||
} data[2];
|
||||
|
||||
data[0].head = capi_iflist;
|
||||
data[0].lock_proc = pbx_capi_lock_interfaces;
|
||||
data[0].unlock_proc = pbx_capi_unlock_interfaces;
|
||||
data[1].head = (struct capi_pvt*)pbx_capi_get_nulliflist();
|
||||
data[1].lock_proc = pbx_capi_nulliflist_lock;
|
||||
data[1].unlock_proc = pbx_capi_nulliflist_unlock;
|
||||
|
||||
if (ast_strlen_zero(requiredChannelName)) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(chancapiCommand)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (strcmp(requiredChannelName, "none") == 0) {
|
||||
int ret = (pbx_capi_cli_exec_capicommand(NULL, chancapiCommand) == 0) ? 0 : -1;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
for (ifc_type = 0; ifc_type < sizeof(data)/sizeof(data[0]); ifc_type++) {
|
||||
search_loops = 10;
|
||||
do {
|
||||
data[ifc_type].lock_proc();
|
||||
for (i = data[ifc_type].head, retry_search = 0; i != 0; i = i->next) {
|
||||
struct ast_channel* c = NULL;
|
||||
|
||||
if ((i->used == 0) || ((i->channeltype != CAPI_CHANNELTYPE_B) &&
|
||||
(i->channeltype != CAPI_CHANNELTYPE_NULL)))
|
||||
continue;
|
||||
if (i->data_plci != 0)
|
||||
continue;
|
||||
|
||||
if (pbx_capi_get_all_locks (i, &c) != 0) {
|
||||
retry_search = 1;
|
||||
break;
|
||||
}
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
const char *cur_name = ast_channel_name(c);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
const char *cur_name = c->name;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
if ((!ast_strlen_zero(cur_name) && (strcmp(requiredChannelName, cur_name) == 0)) ||
|
||||
strcmp(requiredChannelName, i->vname) == 0) {
|
||||
struct ast_channel* usedChannel = c;
|
||||
int ret;
|
||||
|
||||
data[ifc_type].unlock_proc();
|
||||
|
||||
if (i->channeltype != CAPI_CHANNELTYPE_NULL) {
|
||||
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
|
||||
cc_mutex_unlock(&i->lock);
|
||||
ast_channel_unlock(c);
|
||||
} else {
|
||||
ast_channel_unlock(c);
|
||||
ret = (pbx_capi_cli_exec_capicommand(usedChannel, chancapiCommand) == 0) ? 0 : -1;
|
||||
cc_mutex_unlock(&i->lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
cc_mutex_unlock(&i->lock);
|
||||
ast_channel_unlock(c);
|
||||
}
|
||||
data[ifc_type].unlock_proc();
|
||||
if (retry_search != 0) {
|
||||
usleep (100);
|
||||
}
|
||||
} while((retry_search != 0) && (search_loops-- > 0));
|
||||
}
|
||||
|
||||
return -4;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Try to take all locks. Called with false lock order
|
||||
* one of the list locks (iflock or nullif_lock) taken
|
||||
* Used by CLI/AMI
|
||||
*/
|
||||
static int pbx_capi_get_all_locks (struct capi_pvt *i, struct ast_channel** usedChannel)
|
||||
{
|
||||
struct ast_channel* c = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
|
||||
if (c != 0) {
|
||||
if (ast_channel_trylock(c) == 0) {
|
||||
if (ast_mutex_trylock(&i->lock) == 0) {
|
||||
struct ast_channel* cref = (i->channeltype != CAPI_CHANNELTYPE_NULL) ? i->owner : i->used;
|
||||
if (cref == c) {
|
||||
*usedChannel = c;
|
||||
return (0);
|
||||
} else {
|
||||
ast_mutex_unlock(&i->lock);
|
||||
ast_channel_unlock (c);
|
||||
}
|
||||
} else {
|
||||
ast_channel_unlock (c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __CC_MANAGEMENT_COMMON_INTERFACE_H__
|
||||
#define __CC_MANAGEMENT_COMMON_INTERFACE_H__
|
||||
|
||||
|
||||
int pbx_capi_management_capicommand(const char *requiredChannelName, const char *chancapiCommand);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
#include <asterisk/event.h>
|
||||
#endif
|
||||
#include "chan_capi_mwi.h"
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
static unsigned char* time2X208(time_t t);
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
static void pbx_capi_mwi_event(const struct ast_event *event, void *userdata);
|
||||
#endif
|
||||
|
||||
/*
|
||||
MWI command parameters of pbx_capi_mwi
|
||||
*/
|
||||
typedef enum _mwiAddSubscribtionParams {
|
||||
mwiAddSubscribtionController = 1,
|
||||
mwiAddSubscribtionReceivingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiAddSubscribtionReceivingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiAddSubscribtionReceivingUserNumber_PresentationAndScreening,
|
||||
mwiAddSubscribtionReceivingUserNumber,
|
||||
mwiAddSubscribtionControllingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiAddSubscribtionControllingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiAddSubscribtionControllingUserNumber_PresentationAndScreening,
|
||||
mwiAddSubscribtionControllingUserNumber,
|
||||
mwiAddSubscribtionControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
|
||||
mwiAddSubscribtionControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiAddSubscribtionControllingUserProvidedNumber_PresentationAndScreening,
|
||||
mwiAddSubscribtionControllingUserProvidedNumber,
|
||||
mwiAddSubscribtionMax
|
||||
} mwiAddSubscribtionParams_t;
|
||||
|
||||
typedef enum _mwiRemoveSubscribtionParam {
|
||||
mwiRemoveSubscribtionController = 1,
|
||||
mwiRemoveSubscribtionReceivingUserNumber,
|
||||
mwiRemoveSubscribtionMax
|
||||
} mwiRemoveSubscribtionParam_t;
|
||||
|
||||
typedef enum _mwiXmitActivateParams {
|
||||
mwiXmitActivate = 1,
|
||||
mwiXmitActivateController,
|
||||
mwiXmitActivateBasicService,
|
||||
mwiXmitActivateNumberOfMessages,
|
||||
mwiXmitActivateMessageStatus,
|
||||
mwiXmitActivateMessageReference,
|
||||
mwiXmitActivateInvocationMode,
|
||||
mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiXmitActivateReceivingUserNumber_PresentationAndScreening,
|
||||
mwiXmitActivateReceivingUserNumber,
|
||||
mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiXmitActivateControllingUserNumber_PresentationAndScreening,
|
||||
mwiXmitActivateControllingUserNumber,
|
||||
mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
|
||||
mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening,
|
||||
mwiXmitActivateControllingUserProvidedNumber,
|
||||
mwiXmitActivatesMax
|
||||
} mwiXmitActivateParams_t;
|
||||
|
||||
typedef enum _mwiXmitDeactivateParams {
|
||||
mwiXmitDeactivate = 1,
|
||||
mwiXmitDeactivateController,
|
||||
mwiXmitDeactivateBasicService,
|
||||
mwiXmitDeactivateInvocationMode,
|
||||
mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening,
|
||||
mwiXmitDeactivateReceivingUserNumber,
|
||||
mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber,
|
||||
mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
mwiXmitDeactivateControllingUserNumber_PresentationAndScreening,
|
||||
mwiXmitDeactivateControllingUserNumber,
|
||||
mwiXmitDeactivateMax
|
||||
} mwiXmitDeactivateParams_t;
|
||||
|
||||
/*
|
||||
add|controller|fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber|fpn|ton|pres|controllingUserProvidedNumber
|
||||
remove|conntroller|receivingUserNumber
|
||||
xmit|activate|controller|basicService|numberOfMessages|messageStatus|messageReference|invocationMode|
|
||||
fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber|fpn|ton|pres|controllingUserProvidedNumber
|
||||
xmit|deactivate|controller|basicService|invocationMode|fpn|ton|pres|receivingUserNumber|fpn|ton|pres|controllingUserNumber
|
||||
|
||||
add - add MWI subscription
|
||||
remoce - remove MWI subscription
|
||||
xmit - xmit MWI activate or deactivate
|
||||
*/
|
||||
int pbx_capi_mwi(struct ast_channel *c, char *info)
|
||||
{
|
||||
const char* params[MAX((MAX(mwiAddSubscribtionMax, mwiXmitActivatesMax)),(MAX(mwiRemoveSubscribtionMax, mwiXmitDeactivateMax)))];
|
||||
int ret = -1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(params)/sizeof(params[0]); i++) {
|
||||
params[i] = strsep (&info, COMMANDSEPARATOR);
|
||||
}
|
||||
|
||||
if (params[0] == NULL)
|
||||
return (-1);
|
||||
if (strcmp(params[0], "add") == 0) {
|
||||
|
||||
} else if (strcmp (params[0], "remove") == 0) {
|
||||
|
||||
} else if (strcmp (params[0], "xmit") == 0) {
|
||||
if (strcmp (params[mwiXmitActivate], "activate") == 0) {
|
||||
int unit;
|
||||
|
||||
if (params[mwiXmitActivateController] != 0 && params[mwiXmitActivateController][0] != 0) {
|
||||
unit = atoi(params[mwiXmitActivateController]);
|
||||
|
||||
} else {
|
||||
struct capi_pvt *i = CC_CHANNEL_PVT(c);
|
||||
|
||||
unit = (i != 0) ? i->controller : 0;
|
||||
}
|
||||
|
||||
if (pbx_capi_get_controller(unit) != 0 && params[mwiXmitActivateReceivingUserNumber] != 0) {
|
||||
unsigned short basicService = params[mwiXmitActivateBasicService] != 0 ? (unsigned short)atoi(params[mwiXmitActivateBasicService]) : 1;
|
||||
unsigned short numberOfMessages = params[mwiXmitActivateNumberOfMessages] != 0 ? (unsigned int)atoi(params[mwiXmitActivateNumberOfMessages]) : 1;
|
||||
unsigned short messageStatus = params[mwiXmitActivateMessageStatus] != 0 ? (unsigned short)atoi(params[mwiXmitActivateMessageStatus]) : 0;
|
||||
unsigned short messageReference = params[mwiXmitActivateMessageReference] != 0 ? (unsigned short)atoi(params[mwiXmitActivateMessageReference]) : 0;
|
||||
unsigned short invocationMode = params[mwiXmitActivateInvocationMode] != 0 ? (unsigned short)atoi(params[mwiXmitActivateInvocationMode]) : 2;
|
||||
unsigned char ReceivingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
|
||||
(unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_TypeOfFacilityPartyNumber]) : 0;
|
||||
unsigned char ReceivingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
|
||||
unsigned char ReceivingUserNumber_PresentationAndScreening = params[mwiXmitActivateReceivingUserNumber_PresentationAndScreening] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateReceivingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
|
||||
const char* ReceivingUserNumber = params[mwiXmitActivateReceivingUserNumber];
|
||||
unsigned char ControllingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
|
||||
(unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_TypeOfFacilityPartyNumber]) : 0;
|
||||
unsigned char ControllingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
|
||||
unsigned char ControllingUserNumber_PresentationAndScreening = params[mwiXmitActivateControllingUserNumber_PresentationAndScreening] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateControllingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
|
||||
const char* ControllingUserNumber = params[mwiXmitActivateControllingUserNumber];
|
||||
unsigned char ControllingUserProvidedNumber_TypeOfFacilityPartyNumber = params[mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber] != 0 ?
|
||||
(unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_TypeOfFacilityPartyNumber]) : 0;
|
||||
unsigned char ControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
|
||||
unsigned char ControllingUserProvidedNumber_PresentationAndScreening = params[mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitActivateControllingUserProvidedNumber_PresentationAndScreening])) & ~0x80) : 0;
|
||||
const char* ControllingUserProvidedNumber = params[mwiXmitActivateControllingUserProvidedNumber];
|
||||
unsigned char *facilityReceivingUserNumber = pbx_capi_build_facility_number (ReceivingUserNumber_TypeOfFacilityPartyNumber,
|
||||
ReceivingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
ReceivingUserNumber_PresentationAndScreening,
|
||||
ReceivingUserNumber);
|
||||
unsigned char *facilityControllingUserNumber = pbx_capi_build_facility_number (ControllingUserNumber_TypeOfFacilityPartyNumber,
|
||||
ControllingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
ControllingUserNumber_PresentationAndScreening,
|
||||
ControllingUserNumber);
|
||||
unsigned char *facilityControllingUserProvidedNumber = pbx_capi_build_facility_number (ControllingUserProvidedNumber_TypeOfFacilityPartyNumber,
|
||||
ControllingUserProvidedNumber_TypeOfNumberAndNumberingPlan,
|
||||
ControllingUserProvidedNumber_PresentationAndScreening,
|
||||
ControllingUserProvidedNumber);
|
||||
unsigned char* t = time2X208(time(NULL));
|
||||
|
||||
ret = pbx_capi_xmit_mwi(pbx_capi_get_controller(unit),
|
||||
basicService,
|
||||
numberOfMessages,
|
||||
messageStatus,
|
||||
messageReference,
|
||||
invocationMode,
|
||||
facilityReceivingUserNumber,
|
||||
facilityControllingUserNumber,
|
||||
facilityControllingUserProvidedNumber,
|
||||
t);
|
||||
|
||||
ast_free(facilityReceivingUserNumber);
|
||||
ast_free(facilityControllingUserNumber);
|
||||
ast_free(facilityControllingUserProvidedNumber);
|
||||
ast_free(t);
|
||||
}
|
||||
} else if (strcmp (params[mwiXmitDeactivate], "deactivate") == 0) {
|
||||
int unit;
|
||||
|
||||
if (params[mwiXmitDeactivateController] != 0 && params[mwiXmitDeactivateController][0] != 0) {
|
||||
unit = atoi(params[mwiXmitDeactivateController]);
|
||||
|
||||
} else {
|
||||
struct capi_pvt *i = CC_CHANNEL_PVT(c);
|
||||
|
||||
unit = (i != 0) ? i->controller : 0;
|
||||
}
|
||||
if (pbx_capi_get_controller(unit) != 0 && params[mwiXmitDeactivateReceivingUserNumber] != 0) {
|
||||
unsigned short basicService = params[mwiXmitDeactivateBasicService] != 0 ? (unsigned short)atoi(params[mwiXmitDeactivateBasicService]) : 1;
|
||||
unsigned short invocationMode = params[mwiXmitDeactivateInvocationMode] != 0 ? (unsigned short)atoi(params[mwiXmitDeactivateInvocationMode]) : 2;
|
||||
unsigned char ReceivingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
|
||||
(unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_TypeOfFacilityPartyNumber]) : 0;
|
||||
unsigned char ReceivingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
|
||||
unsigned char ReceivingUserNumber_PresentationAndScreening = params[mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitDeactivateReceivingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
|
||||
const char* ReceivingUserNumber = params[mwiXmitDeactivateReceivingUserNumber];
|
||||
unsigned char ControllingUserNumber_TypeOfFacilityPartyNumber = params[mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber] != 0 ?
|
||||
(unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_TypeOfFacilityPartyNumber]) : 0;
|
||||
unsigned char ControllingUserNumber_TypeOfNumberAndNumberingPlan = params[mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_TypeOfNumberAndNumberingPlan])) & ~0x80) : 0;
|
||||
unsigned char ControllingUserNumber_PresentationAndScreening = params[mwiXmitDeactivateControllingUserNumber_PresentationAndScreening] != 0 ?
|
||||
(((unsigned char)atoi(params[mwiXmitDeactivateControllingUserNumber_PresentationAndScreening])) & ~0x80) : 0;
|
||||
const char* ControllingUserNumber = params[mwiXmitDeactivateControllingUserNumber];
|
||||
unsigned char *facilityReceivingUserNumber = pbx_capi_build_facility_number (ReceivingUserNumber_TypeOfFacilityPartyNumber,
|
||||
ReceivingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
ReceivingUserNumber_PresentationAndScreening,
|
||||
ReceivingUserNumber);
|
||||
unsigned char *facilityControllingUserNumber = pbx_capi_build_facility_number (ControllingUserNumber_TypeOfFacilityPartyNumber,
|
||||
ControllingUserNumber_TypeOfNumberAndNumberingPlan,
|
||||
ControllingUserNumber_PresentationAndScreening,
|
||||
ControllingUserNumber);
|
||||
|
||||
ret = pbx_capi_xmit_mwi_deactivate(pbx_capi_get_controller(unit),
|
||||
basicService, invocationMode, facilityReceivingUserNumber, facilityControllingUserNumber);
|
||||
|
||||
ast_free (facilityReceivingUserNumber);
|
||||
ast_free (facilityControllingUserNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int pbx_capi_xmit_mwi(
|
||||
const struct cc_capi_controller *controller,
|
||||
unsigned short basicService,
|
||||
unsigned int numberOfMessages,
|
||||
unsigned short messageStatus,
|
||||
unsigned short messageReference,
|
||||
unsigned short invocationMode,
|
||||
const unsigned char* receivingUserNumber,
|
||||
const unsigned char* controllingUserNumber,
|
||||
const unsigned char* controllingUserProvidedNumber,
|
||||
const unsigned char* timeX208)
|
||||
{
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cword messageNumber = get_capi_MessageNumber();
|
||||
|
||||
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, controller->controller, messageNumber,
|
||||
"w(w(wdwwwssssd))",
|
||||
0x0003, /* Suppl. Service */
|
||||
0x0013, /* MWI Activate */
|
||||
basicService, /* Basic Service */
|
||||
numberOfMessages, /* Number of messages */
|
||||
messageStatus, /* Added messages */
|
||||
messageReference, /* Message reference */
|
||||
invocationMode, /* Invocation mode */
|
||||
receivingUserNumber, /* Receiving user number */
|
||||
controllingUserNumber, /* Controlling user number */
|
||||
controllingUserProvidedNumber, /* Controlling user provided number */
|
||||
timeX208, /* time */
|
||||
messageNumber);
|
||||
|
||||
return ((error == CapiNoError) ? 0 : -1);
|
||||
}
|
||||
|
||||
int pbx_capi_xmit_mwi_deactivate(
|
||||
const struct cc_capi_controller *controller,
|
||||
unsigned short basicService,
|
||||
unsigned short invocationMode,
|
||||
const unsigned char* receivingUserNumber,
|
||||
const unsigned char* controllingUserNumber)
|
||||
{
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cword messageNumber = get_capi_MessageNumber();
|
||||
|
||||
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, controller->controller, messageNumber,
|
||||
"w(w(wwss))",
|
||||
0x0003, /* Suppl. Service */
|
||||
0x0014, /* MWI Activate */
|
||||
basicService, /* Basic Service */
|
||||
invocationMode, /* Invocation mode */
|
||||
receivingUserNumber, /* Receiving user number */
|
||||
controllingUserNumber /* Controlling user number */);
|
||||
|
||||
return ((error == CapiNoError) ? 0 : -1);
|
||||
}
|
||||
|
||||
static unsigned char* time2X208 (time_t t) {
|
||||
unsigned char* ret = 0;
|
||||
#if defined(CC_AST_HAS_VERSION_1_6)
|
||||
unsigned char tX208[] = { 0x0c, 0x32, 0x30, 0x30, 0x31, 0x30, 0x35, 0x31, 0x31, 0x30, 0x39, 0x33, 0x36, 0x00 };
|
||||
struct timeval tv = {
|
||||
.tv_sec = t,
|
||||
};
|
||||
struct ast_tm tm;
|
||||
|
||||
ast_localtime(&tv, &tm, "utc");
|
||||
ast_strftime((char*)&tX208[1], sizeof(tX208)-1, "%Y%d%m%H%M", &tm);
|
||||
|
||||
ret = ast_malloc (sizeof(tX208));
|
||||
if (ret != 0)
|
||||
memcpy (ret, tX208, sizeof(tX208));
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
static void pbx_capi_mwi_event(const struct ast_event *event, void *userdata)
|
||||
{
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion = userdata;
|
||||
/* const char *mbox_context; */
|
||||
const char *mbox_number;
|
||||
int num_messages, num_old_messages;
|
||||
unsigned char* t;
|
||||
int ret;
|
||||
|
||||
mbox_number = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
|
||||
if (ast_strlen_zero(mbox_number)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
mbox_context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
|
||||
if (ast_strlen_zero(mbox_context)) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
|
||||
num_old_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
|
||||
|
||||
t = time2X208 (time(NULL));
|
||||
|
||||
cc_verbose (4, 0, "CAPI%d MWI event for '%s@%s' %d messages\n",
|
||||
mwiSubscribtion->controller->controller,
|
||||
mwiSubscribtion->mailboxNumber+4,
|
||||
mwiSubscribtion->mailboxContext,
|
||||
num_messages);
|
||||
|
||||
if ((num_messages != 0) || (num_old_messages != 0)) {
|
||||
ret = pbx_capi_xmit_mwi(mwiSubscribtion->controller,
|
||||
mwiSubscribtion->basicService,
|
||||
num_messages,
|
||||
0,
|
||||
0,
|
||||
mwiSubscribtion->invocationMode,
|
||||
mwiSubscribtion->mailboxNumber,
|
||||
mwiSubscribtion->controllingUserNumber,
|
||||
mwiSubscribtion->controllingUserProvidedNumber,
|
||||
t);
|
||||
} else {
|
||||
ret = pbx_capi_xmit_mwi_deactivate(mwiSubscribtion->controller,
|
||||
mwiSubscribtion->basicService,
|
||||
mwiSubscribtion->invocationMode,
|
||||
mwiSubscribtion->mailboxNumber,
|
||||
mwiSubscribtion->controllingUserNumber);
|
||||
}
|
||||
|
||||
ast_free(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
void pbx_capi_register_mwi(struct cc_capi_controller *controller)
|
||||
{
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion;
|
||||
|
||||
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
mwiSubscribtion->mwiSubscribtion = ast_event_subscribe(AST_EVENT_MWI, pbx_capi_mwi_event,
|
||||
#ifdef CC_AST_HAS_VERSION_1_8
|
||||
"CHAN_CAPI mbox event",
|
||||
#endif
|
||||
mwiSubscribtion,
|
||||
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, &mwiSubscribtion->mailboxNumber[4],
|
||||
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mwiSubscribtion->mailboxContext,
|
||||
AST_EVENT_IE_END);
|
||||
#endif
|
||||
if (mwiSubscribtion->mwiSubscribtion == 0) {
|
||||
cc_log(LOG_WARNING, "CAPI%d failed to activate MWI subscribtion for '%s@%s'\n",
|
||||
mwiSubscribtion->controller->controller,
|
||||
&mwiSubscribtion->mailboxNumber[4],
|
||||
mwiSubscribtion->mailboxContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbx_capi_refresh_mwi(struct cc_capi_controller *controller)
|
||||
{
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion;
|
||||
|
||||
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
|
||||
if (mwiSubscribtion->mwiSubscribtion != 0) {
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
struct ast_event *event = ast_event_get_cached(AST_EVENT_MWI,
|
||||
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, &mwiSubscribtion->mailboxNumber[4],
|
||||
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mwiSubscribtion->mailboxContext,
|
||||
AST_EVENT_IE_END);
|
||||
if (event != 0) {
|
||||
pbx_capi_mwi_event(event, mwiSubscribtion);
|
||||
ast_event_destroy(event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbx_capi_unregister_mwi(struct cc_capi_controller *controller)
|
||||
{
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion;
|
||||
|
||||
AST_LIST_TRAVERSE(&controller->mwiSubscribtions, mwiSubscribtion, link) {
|
||||
if (mwiSubscribtion->mwiSubscribtion != 0) {
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
ast_event_unsubscribe(mwiSubscribtion->mwiSubscribtion);
|
||||
#endif
|
||||
mwiSubscribtion->mwiSubscribtion = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbx_capi_cleanup_mwi(struct cc_capi_controller *controller)
|
||||
{
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion;
|
||||
|
||||
pbx_capi_unregister_mwi(controller);
|
||||
|
||||
while ((mwiSubscribtion = AST_LIST_REMOVE_HEAD(&controller->mwiSubscribtions, link)) != 0) {
|
||||
ast_free (mwiSubscribtion->mailboxNumber);
|
||||
ast_free (mwiSubscribtion->mailboxContext);
|
||||
ast_free (mwiSubscribtion->controllingUserNumber);
|
||||
ast_free (mwiSubscribtion->controllingUserProvidedNumber);
|
||||
ast_free (mwiSubscribtion);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* pbx_capi_build_facility_number(
|
||||
unsigned char mwifacptynrtype,
|
||||
unsigned char mwifacptynrton,
|
||||
unsigned char mwifacptynrpres,
|
||||
const char* number)
|
||||
{
|
||||
unsigned char* fnr = 0;
|
||||
|
||||
if (number != 0) {
|
||||
fnr = ast_malloc (strlen(number)+7);
|
||||
if (fnr != 0) {
|
||||
fnr[0] = strlen(number) + 3;
|
||||
fnr[1] = mwifacptynrtype;
|
||||
fnr[2] = mwifacptynrton;
|
||||
fnr[3] = mwifacptynrpres | 0x80;
|
||||
strcpy((char*)&fnr[4], number);
|
||||
}
|
||||
}
|
||||
|
||||
return (fnr);
|
||||
}
|
||||
|
||||
/*
|
||||
Init MWI subscriptions
|
||||
*/
|
||||
void pbx_capi_init_mwi_server (
|
||||
struct cc_capi_controller *mwiController,
|
||||
const struct cc_capi_conf *conf) {
|
||||
|
||||
if ((mwiController != 0) && (conf->mwimailbox != 0)) {
|
||||
char* mailboxList = conf->mwimailbox;
|
||||
char* mailboxMember;
|
||||
|
||||
while ((mailboxMember = strsep (&mailboxList, ",")) != 0) {
|
||||
/*
|
||||
Mailbox format: extension[:extension1[:extension2]][@context]
|
||||
*/
|
||||
char* mailboxNumbers = strsep(&mailboxMember, "@");
|
||||
const char* mailboxContext = (mailboxMember != 0) ? mailboxMember : "default";
|
||||
const char* mailboxNumber = strsep (&mailboxNumbers, ":");
|
||||
const char* controllingUserNumber = strsep (&mailboxNumbers, ":");
|
||||
const char* controllingUserProvidedNumber = mailboxNumbers;
|
||||
if ((mailboxNumber != 0) && (*mailboxNumber != 0)) {
|
||||
cc_capi_mwi_mailbox_t* mwiSubscribtion = ast_malloc(sizeof(*mwiSubscribtion));
|
||||
if (mwiSubscribtion != 0) {
|
||||
mwiSubscribtion->mailboxNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, mailboxNumber);
|
||||
mwiSubscribtion->mailboxContext = ast_strdup(mailboxContext);
|
||||
mwiSubscribtion->controllingUserNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, controllingUserNumber);
|
||||
mwiSubscribtion->controllingUserProvidedNumber = pbx_capi_build_facility_number(conf->mwifacptynrtype, conf->mwifacptynrton, conf->mwifacptynrpres, controllingUserProvidedNumber);
|
||||
mwiSubscribtion->controller = mwiController;
|
||||
mwiSubscribtion->mwiSubscribtion = 0;
|
||||
mwiSubscribtion->basicService = conf->mwibasicservice;
|
||||
mwiSubscribtion->invocationMode = conf->mwiinvocation;
|
||||
|
||||
if ((mwiSubscribtion->mailboxNumber == 0) || (mwiSubscribtion->mailboxContext == 0) ||
|
||||
((mwiSubscribtion->controllingUserNumber == 0) && (controllingUserNumber != 0)) ||
|
||||
((mwiSubscribtion->controllingUserProvidedNumber == 0) && (controllingUserProvidedNumber != 0))) {
|
||||
ast_free(mwiSubscribtion->mailboxNumber);
|
||||
ast_free(mwiSubscribtion->mailboxContext);
|
||||
ast_free(mwiSubscribtion->controllingUserNumber);
|
||||
ast_free(mwiSubscribtion->controllingUserProvidedNumber);
|
||||
ast_free(mwiSubscribtion);
|
||||
} else {
|
||||
cc_verbose (4, 0, "CAPI%d add MWI subscribtion for '%s@%s' user '%s' control '%s'\n",
|
||||
mwiSubscribtion->controller->controller,
|
||||
mwiSubscribtion->mailboxNumber + 4,
|
||||
mwiSubscribtion->mailboxContext,
|
||||
(mwiSubscribtion->controllingUserNumber != 0) ? (char*)mwiSubscribtion->controllingUserNumber+4 : "",
|
||||
(mwiSubscribtion->controllingUserProvidedNumber != 0) ? (char*)mwiSubscribtion->controllingUserProvidedNumber+4 : "");
|
||||
|
||||
memset(&mwiSubscribtion->link, 0x00, sizeof(mwiSubscribtion->link));
|
||||
AST_LIST_INSERT_TAIL(&mwiController->mwiSubscribtions, mwiSubscribtion, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __CHAN_CAPI_MWI_H__
|
||||
#define __CHAN_CAPI_MWI_H__
|
||||
|
||||
extern int pbx_capi_mwi(struct ast_channel *c, char *info);
|
||||
extern int pbx_capi_xmit_mwi(
|
||||
const struct cc_capi_controller *controller,
|
||||
unsigned short basicService,
|
||||
unsigned int numberOfMessages,
|
||||
unsigned short messageStatus,
|
||||
unsigned short messageReference,
|
||||
unsigned short invocationMode,
|
||||
const unsigned char* receivingUserNumber,
|
||||
const unsigned char* controllingUserNumber,
|
||||
const unsigned char* controllingUserProvidedNumber,
|
||||
const unsigned char* timeX208);
|
||||
extern int pbx_capi_xmit_mwi_deactivate(
|
||||
const struct cc_capi_controller *controller,
|
||||
unsigned short basicService,
|
||||
unsigned short invocationMode,
|
||||
const unsigned char* receivingUserNumber,
|
||||
const unsigned char* controllingUserNumber);
|
||||
extern void pbx_capi_register_mwi(struct cc_capi_controller *controller);
|
||||
extern void pbx_capi_refresh_mwi(struct cc_capi_controller *controller);
|
||||
extern void pbx_capi_unregister_mwi(struct cc_capi_controller *controller);
|
||||
extern void pbx_capi_cleanup_mwi(struct cc_capi_controller *controller);
|
||||
extern unsigned char* pbx_capi_build_facility_number(
|
||||
unsigned char mwifacptynrtype,
|
||||
unsigned char mwifacptynrton,
|
||||
unsigned char mwifacptynrpres,
|
||||
const char* number);
|
||||
|
||||
void pbx_capi_init_mwi_server (
|
||||
struct cc_capi_controller *mwiController,
|
||||
const struct cc_capi_conf *conf);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __CHAN_CAPI_PLATFORM_H__
|
||||
#define __CHAN_CAPI_PLATFORM_H__
|
||||
|
||||
#if __GNUC__ >= 3 /* { */
|
||||
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
#else /* } { */
|
||||
|
||||
#ifndef likely
|
||||
#define likely(__x__) (!!(__x__))
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(__x__) (!!(__x__))
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* (QSIG)
|
||||
*
|
||||
* Implementation of QSIG extensions for chan_capi
|
||||
*
|
||||
* Copyright 2006-2007 (c) Mario Goegel
|
||||
*
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef PBX_QSIG_H
|
||||
#define PBX_QSIG_H
|
||||
|
||||
int capiqsigdebug;
|
||||
|
||||
#define QSIG_DISABLED 0x00
|
||||
#define QSIG_ENABLED 0x01 /* shouldn't be used anymore */
|
||||
|
||||
#define QSIG_TYPE_ALCATEL_ECMA 0x01 /* use additional Alcatel ECMA */
|
||||
#define QSIG_TYPE_HICOM_ECMAV2 0x02 /* use additional Hicom ECMA V2 */
|
||||
|
||||
#define CAPI_QSIG_WAITEVENT_PRPROPOSE 0x01000000
|
||||
|
||||
|
||||
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
|
||||
#define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
|
||||
#define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
|
||||
#define Q932_PROTOCOL_GAT 0x16
|
||||
#define Q932_PROTOCOL_EXTENSIONS 0x1F
|
||||
|
||||
#define COMP_TYPE_INVOKE 0xa1 /* Invoke component */
|
||||
#define COMP_TYPE_DISCR_SS 0x91 /* Supplementary service descriptor - ROSE PROTOCOL */
|
||||
#define COMP_TYPE_NFE 0xaa /* Network Facility Extensions (ECMA-165) */
|
||||
#define COMP_TYPE_APDU_INTERP 0x8b /* APDU Interpration Type (0 DISCARD, 1 CLEARCALL-IF-UNKNOWN, 2 REJECT-APDU) */
|
||||
#define COMP_TYPE_RETURN_RESULT 0xA2
|
||||
#define COMP_TYPE_RETURN_ERROR 0xA3
|
||||
#define COMP_TYPE_REJECT 0xA4
|
||||
|
||||
#define APDUINTERPRETATION_IGNORE 0x00
|
||||
#define APDUINTERPRETATION_CLEARCALL 0x01
|
||||
#define APDUINTERPRETATION_REJECT 0x02
|
||||
|
||||
/* const char* APDU_STR[] = { "IGNORE APDU", "CLEARCALL-IF-UNKNOWN", "REJECT APDU" }; */
|
||||
|
||||
|
||||
/* ASN.1 Identifier Octet - Data types */
|
||||
#define ASN1_TYPE_MASK 0x1f
|
||||
#define ASN1_BOOLEAN 0x01
|
||||
#define ASN1_INTEGER 0x02
|
||||
#define ASN1_BITSTRING 0x03
|
||||
#define ASN1_OCTETSTRING 0x04
|
||||
#define ASN1_NULL 0x05
|
||||
#define ASN1_OBJECTIDENTIFIER 0x06
|
||||
#define ASN1_OBJECTDESCRIPTOR 0x07
|
||||
#define ASN1_EXTERN 0x08
|
||||
#define ASN1_REAL 0x09
|
||||
#define ASN1_ENUMERATED 0x0a
|
||||
#define ASN1_EMBEDDEDPDV 0x0b
|
||||
#define ASN1_UTF8STRING 0x0c
|
||||
#define ASN1_RELATIVEOBJECTID 0x0d
|
||||
/* 0x0e & 0x0f are reserved for future ASN.1 editions */
|
||||
#define ASN1_SEQUENCE 0x10
|
||||
#define ASN1_SET 0x11
|
||||
#define ASN1_NUMERICSTRING 0x12
|
||||
#define ASN1_PRINTABLESTRING 0x13
|
||||
#define ASN1_TELETEXSTRING 0x14
|
||||
#define ASN1_IA5STRING 0x16
|
||||
#define ASN1_UTCTIME 0x17
|
||||
#define ASN1_GENERALIZEDTIME 0x18
|
||||
|
||||
/* ASN.1 Type/Tag Class (bits 7 & 6 of Tag octet) */
|
||||
#define ASN1_TC_UNIVERSAL 0x00
|
||||
#define ASN1_TC_APPLICATION 0x40
|
||||
#define ASN1_TC_CONTEXTSPEC 0x80
|
||||
#define ASN1_TC_PRIVATE 0xC0
|
||||
|
||||
/* ASN.1 Type/Tag Form (bit 5 of Tag octet) */
|
||||
#define ASN1_TF_PRIMITVE 0x00
|
||||
#define ASN1_TF_CONSTRUCTED 0x20 /* field may be a type of sequence or set */
|
||||
|
||||
#define CNIP_CALLINGNAME 0x00 /* Name-Types defined in ECMA-164 */
|
||||
#define CNIP_CALLEDNAME 0x01
|
||||
#define CNIP_CONNECTEDNAME 0x02
|
||||
#define CNIP_BUSYNAME 0x03
|
||||
|
||||
|
||||
#define CNIP_NAMEPRESALLOW 0x80
|
||||
#define CNIP_NAMEPRESRESTR 0xA0
|
||||
#define CNIP_NAMEPRESUNAVAIL 0xC0
|
||||
|
||||
#define CNIP_NAMEUSERPROVIDED 0x00 /* Name is User-provided, unvalidated */
|
||||
#define CNIP_NAMEUSERPROVIDEDV 0x01 /* Name is User-provided and validated */
|
||||
|
||||
/* QSIG Operations += 1000 */
|
||||
#define CCQSIG__ECMA__NAMEPRES 1000 /* Setting an own constant for ECMA Operation/Namepresentation, others will follow */
|
||||
#define CCQSIG__ECMA__PRPROPOSE 1004 /* Path Replacement Propose */
|
||||
#define CCQSIG__ECMA__CTCOMPLETE 1012 /* Call Transfer Complete */
|
||||
#define CCQSIG__ECMA__LEGINFO2 1021 /* LEG INFORMATION2 */
|
||||
#define CCQSIG__ECMA__LEGINFO3 1022 /* LEG INFORMATION3 */
|
||||
|
||||
|
||||
#define CCQSIG_TIMER_WAIT_PRPROPOSE 1 /* Wait x seconds */
|
||||
|
||||
struct rose_component {
|
||||
u_int8_t type;
|
||||
u_int8_t len;
|
||||
u_int8_t data[0];
|
||||
};
|
||||
|
||||
#define GET_COMPONENT(component, idx, ptr, length) \
|
||||
if ((idx)+2 > (length)) \
|
||||
break; \
|
||||
(component) = (struct rose_component*)&((ptr)[idx]); \
|
||||
if ((idx)+(component)->len+2 > (length)) { \
|
||||
if ((component)->len != ASN1_LEN_INDEF) \
|
||||
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
|
||||
}
|
||||
|
||||
#define NEXT_COMPONENT(component, idx) \
|
||||
(idx) += (component)->len + 2
|
||||
|
||||
#define SUB_COMPONENT(component, idx) \
|
||||
(idx) += 2
|
||||
|
||||
#define CHECK_COMPONENT(component, comptype, message) \
|
||||
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
|
||||
pri_message(pri, (message), (component)->type); \
|
||||
asn1_dump(pri, (component), (component)->len+2); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define ASN1_GET_INTEGER(component, variable) \
|
||||
do { \
|
||||
int comp_idx; \
|
||||
(variable) = 0; \
|
||||
for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
|
||||
(variable) = ((variable) << 8) | (component)->data[comp_idx]; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_FIXUP_LEN(component, size) \
|
||||
do { \
|
||||
if ((component)->len == ASN1_LEN_INDEF) \
|
||||
size += 2; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
|
||||
do { \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
(component)->len = 0; \
|
||||
(idx) += 2; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
|
||||
do { \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
(component)->len = 1; \
|
||||
(component)->data[0] = (value); \
|
||||
(idx) += 3; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
|
||||
do { \
|
||||
int __val = (value); \
|
||||
int __i = 0; \
|
||||
(component) = (struct rose_component *)&((ptr)[(idx)]); \
|
||||
(component)->type = (comptype); \
|
||||
if ((__val >> 24)) \
|
||||
(component)->data[__i++] = (__val >> 24) & 0xff; \
|
||||
if ((__val >> 16)) \
|
||||
(component)->data[__i++] = (__val >> 16) & 0xff; \
|
||||
if ((__val >> 8)) \
|
||||
(component)->data[__i++] = (__val >> 8) & 0xff; \
|
||||
(component)->data[__i++] = __val & 0xff; \
|
||||
(component)->len = __i; \
|
||||
(idx) += 2 + __i; \
|
||||
} while (0)
|
||||
|
||||
#define ASN1_PUSH(stack, stackpointer, component) \
|
||||
(stack)[(stackpointer)++] = (component)
|
||||
|
||||
#define ASN1_FIXUP(stack, stackpointer, data, idx) \
|
||||
do { \
|
||||
--(stackpointer); \
|
||||
(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define free_null(x) { ast_free(x); x = NULL; }
|
||||
|
||||
/* Common QSIG structs */
|
||||
|
||||
/*
|
||||
* INVOKE Data struct, contains data for further operations
|
||||
*/
|
||||
struct cc_qsig_invokedata {
|
||||
int len; /* invoke length */
|
||||
int offset; /* where does the invoke start in facility array */
|
||||
int id; /* id from sent Invoke Number */
|
||||
int apdu_interpr; /* What To Do with unknown Operation? */
|
||||
int descr_type; /* component descriptor is of ASN.1 Datatype (0x02 Integer, 0x06 Object Identifier) */
|
||||
int type; /* when component is Integer */
|
||||
int oid_len;
|
||||
unsigned char oid_bin[20]; /* when component is Object Identifier then save here the binary oid */
|
||||
int datalen; /* invoke struct len */
|
||||
unsigned char data[255]; /* invoke */
|
||||
};
|
||||
|
||||
/*
|
||||
* NFE Entity Address - contains destination informations for following INVOKE's
|
||||
*/
|
||||
struct cc_qsig_entityaddr { /* In case of AnyPINX */
|
||||
int partynum; /* private,public,etc a5=private */
|
||||
int ton; /* Type of Number */
|
||||
unsigned char *num; /* EntityNumber */
|
||||
};
|
||||
|
||||
/*
|
||||
* Network Facility Extensions struct - to which pbx does the INVOKE belong to
|
||||
*/
|
||||
struct cc_qsig_nfe {
|
||||
int src_entity; /* Call is coming from PBX (End|Any) */
|
||||
int dst_entity; /* Call destination is */
|
||||
struct cc_qsig_entityaddr src_addr; /* additional infos (PBX identifier) */
|
||||
struct cc_qsig_entityaddr dst_addr; /* same here for destination */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
|
||||
/*
|
||||
*** QSIG Core Functions
|
||||
*/
|
||||
extern void cc_qsig_verbose(int c_d, char *text, ...);
|
||||
|
||||
extern int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int protocolvar, int apdu_interpr, struct cc_qsig_nfe *nfe);
|
||||
extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
|
||||
extern unsigned int cc_qsig_asn1_get_string(unsigned char *buf, int buflen, unsigned char *data);
|
||||
extern unsigned int cc_qsig_asn1_get_integer(unsigned char *data, int *idx);
|
||||
extern unsigned char *cc_qsig_asn1_oid2str(unsigned char *data, int size);
|
||||
extern int cc_qsig_asn1_add_string2(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
|
||||
extern unsigned int cc_qsig_asn1_add_string(unsigned char *buf, int *idx, char *data, int datalen);
|
||||
extern unsigned int cc_qsig_asn1_add_integer(unsigned char *buf, int *idx, int value);
|
||||
|
||||
extern signed int cc_qsig_asn1_check_ecma_isdn_oid(unsigned char *data, int len);
|
||||
extern unsigned int cc_qsig_check_facility(unsigned char *data, int *idx, int *apduval, int protocol);
|
||||
extern signed int cc_qsig_check_invoke(unsigned char *data, int *idx);
|
||||
extern signed int cc_qsig_get_invokeid(unsigned char *data, int *idx, struct cc_qsig_invokedata *invoke);
|
||||
extern signed int cc_qsig_fill_invokestruct(unsigned char *data, int *idx, struct cc_qsig_invokedata *invoke, int apduval);
|
||||
extern unsigned int cc_qsig_handle_capiind(unsigned char *data, struct capi_pvt *i);
|
||||
extern unsigned int cc_qsig_handle_capi_facilityind(unsigned char *data, struct capi_pvt *i);
|
||||
extern unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_answer_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_alert_data(unsigned char *data, struct capi_pvt *i, struct ast_channel *c);
|
||||
extern unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct capi_pvt *i, int facility);
|
||||
|
||||
extern signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protocol);
|
||||
extern unsigned int cc_qsig_handle_invokeoperation(int invokeident, struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
|
||||
extern unsigned int cc_qsig_do_facility(unsigned char *fac, struct ast_channel *c, char *param, unsigned int factype, int info1);
|
||||
|
||||
extern int pbx_capi_qsig_getplci(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_ssct(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_ct(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_callmark(struct ast_channel *c, char *param);
|
||||
extern int pbx_capi_qsig_bridge(struct capi_pvt *i0, struct capi_pvt *i1);
|
||||
extern int pbx_capi_qsig_sendtext(struct ast_channel *c, const char *text);
|
||||
|
||||
|
||||
extern void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp);
|
||||
extern void cc_pbx_qsig_conf_interface_value(struct cc_capi_conf *conf, struct ast_variable *v);
|
||||
extern void interface_cleanup_qsig(struct capi_pvt *i);
|
||||
extern void pbx_capi_qsig_unload_module(struct capi_pvt *i);
|
||||
extern void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2008 Cytronics & Melware
|
||||
* Copyright (C) 2007 Mario Goegel
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decoding of addressing-data-elements from asn1-97
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_qsig_ecma.h"
|
||||
#include "chan_capi_qsig_asn197ade.h"
|
||||
|
||||
/*
|
||||
* Returns an "Party Number" from an string, encoded as in addressing-data-elements-asn1-97
|
||||
* data should be a buffer with max. 20 bytes, according to spec
|
||||
* return:
|
||||
* index counter
|
||||
*/
|
||||
unsigned int cc_qsig_asn197ade_get_partynumber(char *buf, int buflen, int *idx, unsigned char *data)
|
||||
{
|
||||
int myidx = *idx;
|
||||
int datalength;
|
||||
int numtype;
|
||||
|
||||
datalength = data[myidx++];
|
||||
|
||||
if (!datalength) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
numtype = (data[myidx++] & 0x0F); /* defines type of Number: numDigits, publicPartyNum, nsapEncNum, dataNumDigits */
|
||||
|
||||
/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */
|
||||
switch (numtype){
|
||||
case 0:
|
||||
if (data[myidx] > 0) { /* length of this context data */
|
||||
if (data[myidx+1] == ASN1_TC_CONTEXTSPEC) {
|
||||
myidx += 2;
|
||||
myidx += cc_qsig_asn197ade_get_numdigits(buf, buflen, &myidx, data);
|
||||
} else {
|
||||
myidx += cc_qsig_asn197ade_get_numdigits(buf, buflen, &myidx, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: /* publicPartyNumber (E.164) not supported yet */
|
||||
return 0;
|
||||
break;
|
||||
case 2: /* NsapEncodedNumber (some ATM stuff) not supported yet */
|
||||
return 0;
|
||||
break;
|
||||
case 3:
|
||||
if (data[myidx++] > 0) { /* length of this context data */
|
||||
if (data[myidx+1] == ASN1_TC_CONTEXTSPEC) {
|
||||
myidx += 2;
|
||||
myidx += cc_qsig_asn197ade_get_numdigits(buf, buflen, &myidx, data);
|
||||
} else {
|
||||
myidx += cc_qsig_asn197ade_get_numdigits(buf, buflen, &myidx, data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
};
|
||||
/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */
|
||||
return myidx - *idx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an string from ASN.1 encoded string
|
||||
*/
|
||||
unsigned int cc_qsig_asn197ade_get_numdigits(char *buf, int buflen, int *idx, unsigned char *data)
|
||||
{
|
||||
int strsize;
|
||||
int myidx = *idx;
|
||||
|
||||
strsize = data[myidx++];
|
||||
if (strsize > buflen)
|
||||
strsize = buflen;
|
||||
memcpy(buf, &data[myidx], strsize);
|
||||
buf[strsize] = 0;
|
||||
|
||||
/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * string length %i,%i\n", strsize, *idx); */
|
||||
return strsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an string from ASN.1 encoded string
|
||||
*/
|
||||
unsigned int cc_qsig_asn197ade_add_numdigits(char *buf, int buflen, int *idx, unsigned char *data)
|
||||
{
|
||||
int myidx=0;
|
||||
|
||||
if ((1 + buflen) > sizeof(*buf)) {
|
||||
/* String exceeds buffer size */
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[myidx++] = buflen;
|
||||
memcpy(&buf[myidx], data, buflen);
|
||||
myidx = 1 + strlen(buf);
|
||||
return myidx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an "PresentedNumberScreened" from an string, encoded as in addressing-data-elements-asn1-97
|
||||
* data is pointer to PresentedNumberScreened struct
|
||||
* return:
|
||||
* index counter
|
||||
*/
|
||||
unsigned int cc_qsig_asn197ade_get_pns(unsigned char *data, int *idx, struct asn197ade_numberscreened *ns)
|
||||
{ /* sample data: a0 08 80 03>513<0a 01 00 */
|
||||
int myidx = *idx;
|
||||
char buf[ASN197ADE_NUMDIGITS_STRSIZE+1];
|
||||
unsigned int buflen = sizeof(buf);
|
||||
unsigned res;
|
||||
int numtype;
|
||||
|
||||
ns->partyNumber = NULL;
|
||||
ns->screeningInd = userProvidedNotScreened;
|
||||
|
||||
numtype = (data[myidx++] & 0x0F); /* defines type of Number */
|
||||
|
||||
/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * num type %i,%i\n", numtype, myidx); */
|
||||
switch (numtype){
|
||||
case 0:
|
||||
/* myidx points now to length */
|
||||
res = cc_qsig_asn197ade_get_partynumber(buf, buflen, &myidx, data);
|
||||
/* cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * res %i\n", numtype); */
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
myidx += res;
|
||||
if (strlen(buf)) {
|
||||
ns->partyNumber = ast_strdup(buf);
|
||||
}
|
||||
|
||||
/* get screening indicator */
|
||||
if (data[myidx] == ASN1_ENUMERATED) { /* HACK: this is not safe - check length of this parameter */
|
||||
myidx++;
|
||||
ns->screeningInd = cc_qsig_asn1_get_integer(data, &myidx);
|
||||
}
|
||||
|
||||
break;
|
||||
case 1: /* presentation restricted */
|
||||
myidx += data[myidx] + 1; /* this val should be zero */
|
||||
break;
|
||||
case 2: /* number not available due to interworking */
|
||||
myidx += data[myidx] + 1; /* this val should be zero */
|
||||
break;
|
||||
case 3:
|
||||
/* myidx points now to length */
|
||||
res = cc_qsig_asn197ade_get_partynumber(buf, buflen, &myidx, data);
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
myidx += res;
|
||||
if (strlen(buf)) {
|
||||
ns->partyNumber = ast_strdup(buf);
|
||||
}
|
||||
|
||||
/* get screening indicator */
|
||||
if (data[myidx] == ASN1_ENUMERATED) { /* HACK: this is not safe - check length of this parameter */
|
||||
myidx++;
|
||||
ns->screeningInd = cc_qsig_asn1_get_integer(data, &myidx);
|
||||
}
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
return myidx - *idx;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2008 Cytronics & Melware
|
||||
* Copyright (C) 2007 Mario Goegel
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decoding of addressing-data-elements from asn1-97
|
||||
*/
|
||||
|
||||
#ifndef PBX_QSIG_ASN197ADE_H
|
||||
#define PBX_QSIG_ASN197ADE_H
|
||||
|
||||
#define ASN197ADE_NUMDIGITS_STRSIZE 20
|
||||
|
||||
struct asn197ade_numberscreened {
|
||||
char *partyNumber;
|
||||
enum {
|
||||
userProvidedNotScreened,
|
||||
userProvidedVerifiedAndPassed,
|
||||
userProvidedVerifiedAndFailed,
|
||||
networkProvided
|
||||
} screeningInd;
|
||||
};
|
||||
|
||||
extern unsigned int cc_qsig_asn197ade_get_partynumber(char *buf, int buflen, int *idx, unsigned char *data);
|
||||
extern unsigned int cc_qsig_asn197ade_get_numdigits(char *buf, int buflen, int *idx, unsigned char *data);
|
||||
|
||||
extern unsigned int cc_qsig_asn197ade_add_numdigits(char *buf, int buflen, int *idx, unsigned char *data);
|
||||
|
||||
extern unsigned int cc_qsig_asn197ade_get_pns(unsigned char *data, int *idx, struct asn197ade_numberscreened *ns);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2008 Cytronics & Melware
|
||||
* Copyright (C) 2007 Mario Goegel
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decoding of name-operations from asn1-97
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_qsig_ecma.h"
|
||||
#include "chan_capi_qsig_asn197no.h"
|
||||
|
||||
/*
|
||||
* Returns an "Name" from an string, encoded as in name-operations-asn1-97
|
||||
* data should be a buffer with max. 50 bytes, according to spec
|
||||
* bufds returns size of name in "buf"
|
||||
* return:
|
||||
* index counter
|
||||
*/
|
||||
|
||||
unsigned int cc_qsig_asn197no_get_name(char *buf, int buflen, unsigned int *bufds, int *idx, unsigned char *data)
|
||||
{
|
||||
int myidx = *idx;
|
||||
unsigned int nametag;
|
||||
unsigned int namelength = 0;
|
||||
unsigned int nametype;
|
||||
unsigned int namesetlength = 0;
|
||||
unsigned int namepres;
|
||||
unsigned int charset = 1;
|
||||
unsigned int seqlength = 0;
|
||||
|
||||
nametag = data[myidx++];
|
||||
if (nametag == (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
|
||||
/* This facility is encoded as SEQUENCE */
|
||||
seqlength = data[++myidx];
|
||||
myidx++;
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Got name sequence (Length= %i)\n", seqlength);
|
||||
}
|
||||
|
||||
if (nametag < 0x80) { /* Tag shows an simple String */
|
||||
namelength = cc_qsig_asn1_get_string((unsigned char *)buf, buflen, &data[myidx]);
|
||||
} else { /* Tag shows an context specific String */
|
||||
nametype = (nametag & 0x0F); /* Type of Name-Struct */
|
||||
namepres = nametype; /* Name Presentation or Restriction */
|
||||
|
||||
switch (nametype) {
|
||||
case 0: /* Simple Name */
|
||||
case 2: /* [LENGTH] [STRING] */
|
||||
namelength = cc_qsig_asn1_get_string((unsigned char *)buf, buflen, &data[myidx]);
|
||||
break;
|
||||
case 1: /* Nameset */
|
||||
case 3: /* [LENGTH] [BIT-STRING] [LENGTH] [STRING] [INTEGER] [LENGTH] [VALUE] */
|
||||
namesetlength = data[myidx++];
|
||||
if (data[myidx++] == ASN1_OCTETSTRING) {
|
||||
/* should be so */
|
||||
namelength = cc_qsig_asn1_get_string((unsigned char *)buf, buflen, &data[myidx]);
|
||||
myidx += namelength + 1;
|
||||
} else {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (String expected)\n");
|
||||
break;
|
||||
}
|
||||
if (data[myidx++] == ASN1_INTEGER) {
|
||||
charset = cc_qsig_asn1_get_integer(data, &myidx);
|
||||
} else {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " Namestruct not ECMA conform (Integer expected)\n");
|
||||
}
|
||||
break;
|
||||
case 4: /* Name not available */
|
||||
break;
|
||||
case 7: /* Namepres. restricted NULL - don't understand ECMA-164, Page 5 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (namelength > 0) {
|
||||
myidx += namelength + 1;
|
||||
*bufds = namelength;
|
||||
return myidx - *idx;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2008 Cytronics & Melware
|
||||
* Copyright (C) 2007 Mario Goegel
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Decoding of name-operations from asn1-97
|
||||
*/
|
||||
|
||||
#ifndef PBX_QSIG_ASN197NO_H
|
||||
#define PBX_QSIG_ASN197NO_H
|
||||
|
||||
#define ASN197NO_NAME_STRSIZE 50
|
||||
|
||||
extern unsigned int cc_qsig_asn197no_get_name(char *buf, int buflen, unsigned int *bufds, int *idx, unsigned char *data);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,885 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2008 Cytronics & Melware
|
||||
* Copyright (C) 2007 Mario Goegel
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#include "chan_capi_qsig.h"
|
||||
#include "chan_capi_qsig_ecma.h"
|
||||
#include "chan_capi_qsig_asn197ade.h"
|
||||
#include "chan_capi_qsig_asn197no.h"
|
||||
|
||||
|
||||
/*
|
||||
* Handle Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION
|
||||
*
|
||||
* This function decodes the namepresentation facility
|
||||
* The name will be copied in the cid.cid_name field of the asterisk channel struct
|
||||
*
|
||||
* parameters
|
||||
* invoke struct, which contains encoded data from facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* nothing
|
||||
*/
|
||||
void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
|
||||
{
|
||||
char callername[51]; /* ECMA defines max length to 50 */
|
||||
unsigned int namelength = 0;
|
||||
unsigned int datalength;
|
||||
int myidx = 0;
|
||||
char *nametype = NULL;
|
||||
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling Name Operation (id# %#x)\n", invoke->id);
|
||||
|
||||
callername[0] = 0;
|
||||
datalength = invoke->datalen;
|
||||
|
||||
myidx = cc_qsig_asn197no_get_name(callername, ASN197NO_NAME_STRSIZE, &namelength, &myidx, invoke->data );
|
||||
|
||||
if (namelength == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Maybe we do some charset conversions */
|
||||
|
||||
switch (invoke->type) {
|
||||
case 0: /* Calling Name */
|
||||
nametype = "CALLING NAME";
|
||||
break;
|
||||
case 1: /* Called Name */
|
||||
nametype = "CALLED NAME";
|
||||
break;
|
||||
case 2: /* Connected Name */
|
||||
nametype = "CONNECTED NAME";
|
||||
break;
|
||||
case 3: /* Busy Name */
|
||||
nametype = "BUSY NAME";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (invoke->type) {
|
||||
case 0: /* Calling Name */
|
||||
#ifdef CC_AST_HAS_VERSION_1_8
|
||||
/* ast_set_callerid updates CDR, but __ast_pbx_run updates CDR too.
|
||||
__ast_pbx_run does not uses the channel lock and this results in destruction
|
||||
of CDR list
|
||||
Do notcall this function until problem resolved
|
||||
ast_set_callerid(i->owner, NULL, callername, NULL);
|
||||
Use code from ast_set_callerid but do not update CDR
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
ast_channel_caller(i->owner)->id.name.valid = 1;
|
||||
ast_free(ast_channel_caller(i->owner)->id.name.str);
|
||||
ast_channel_caller(i->owner)->id.name.str = ast_strdup(callername);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
i->owner->caller.id.name.valid = 1;
|
||||
ast_free(i->owner->caller.id.name.str);
|
||||
i->owner->caller.id.name.str = ast_strdup(callername);
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
#else
|
||||
i->owner->cid.cid_name = ast_strdup(callername); /* Save name to callerid */
|
||||
#endif
|
||||
break;
|
||||
case 1: /* Called Name */
|
||||
case 2: /* Connected Name */
|
||||
case 3: /* Busy Name */
|
||||
if (i->qsig_data.dnameid) { /* this facility may come more than once - if so, then update this value */
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * deleting previously received name.\n", nametype, namelength, callername);
|
||||
ast_free(i->qsig_data.dnameid);
|
||||
}
|
||||
i->qsig_data.dnameid = ast_strdup(callername); /* save name as destination in qsig specific fields */
|
||||
/* there's no similarly field in asterisk */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got %s: \"%s\" (%i byte(s))\n", nametype, callername, namelength);
|
||||
|
||||
/* if there was an sequence tag, we have more informations here, but we will ignore it at the moment */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.0-3 ECMA/ISDN/NAMEPRESENTATION
|
||||
*
|
||||
* This function encodes the namepresentation facility
|
||||
* The name will be copied from the cid.cid_name field of the asterisk channel struct.
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, const char * name)
|
||||
{
|
||||
unsigned char namebuf[51];
|
||||
unsigned char data[255];
|
||||
int dataidx = 0;
|
||||
int namelen = 0;
|
||||
|
||||
if (name)
|
||||
namelen = strlen(name);
|
||||
|
||||
if (namelen < 1) { /* There's no name available, try to take Interface-Name */
|
||||
if (i->name) {
|
||||
if (strlen(i->name) >= 1) {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
namelen = strlen(i->name);
|
||||
memcpy(namebuf, i->name, namelen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
memcpy(namebuf, name, namelen);
|
||||
}
|
||||
namebuf[namelen] = 0;
|
||||
|
||||
invoke->id = 1;
|
||||
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
|
||||
invoke->type = (nametype % 4); /* Invoke Operation Number, if OID it's the last byte*/
|
||||
|
||||
if (namelen>0) {
|
||||
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
|
||||
data[dataidx++] = namelen;
|
||||
memcpy(&data[dataidx], namebuf, namelen);
|
||||
dataidx += namelen;
|
||||
} else {
|
||||
data[dataidx++] = 0x84; /* Name not available */
|
||||
data[dataidx++] = 0;
|
||||
}
|
||||
|
||||
invoke->datalen = dataidx;
|
||||
memcpy(invoke->data, data, dataidx);
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending \"%s\": (%i byte(s))\n", namebuf, namelen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.22 ECMA/ISDN/LEG_INFO3
|
||||
*
|
||||
* This function encodes the namepresentation facility
|
||||
* The name will be copied from the cid.cid_name field of the asterisk channel struct.
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name)
|
||||
{
|
||||
unsigned char namebuf[51];
|
||||
unsigned char data[255];
|
||||
|
||||
int dataidx = 0;
|
||||
int namelen = 0;
|
||||
|
||||
if (name)
|
||||
namelen = strlen(name);
|
||||
|
||||
if (namelen < 1) { /* There's no name available, try to take Interface-Name */
|
||||
if (i->name) {
|
||||
if (strlen(i->name) >= 1) {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
namelen = strlen(i->name);
|
||||
memcpy(namebuf, i->name, namelen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (namelen > 50)
|
||||
namelen = 50;
|
||||
memcpy(namebuf, name, namelen);
|
||||
}
|
||||
|
||||
invoke->id = 1;
|
||||
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
|
||||
invoke->type = 22; /* Invoke Operation Number, if OID it's the last byte*/
|
||||
|
||||
data[dataidx++] = ASN1_TF_CONSTRUCTED | ASN1_SEQUENCE;
|
||||
data[dataidx++] = 5 + namelen;
|
||||
|
||||
data[dataidx++] = ASN1_BOOLEAN; /* PresentationAllowedIndicator */
|
||||
data[dataidx++] = 1;
|
||||
data[dataidx++] = 1;
|
||||
|
||||
if (namelen>0) {
|
||||
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
|
||||
data[dataidx++] = namelen;
|
||||
memcpy(&data[dataidx], namebuf, namelen);
|
||||
dataidx += namelen;
|
||||
} else {
|
||||
data[dataidx++] = 0x84; /* Name not available */
|
||||
data[dataidx++] = 0;
|
||||
}
|
||||
|
||||
invoke->datalen = dataidx;
|
||||
memcpy(invoke->data, data, dataidx);
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_LEG_INFO3 \"%s\": (%i byte(s))\n", namebuf, namelen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handle Operation: 1.3.12.9.21 ECMA/ISDN/LEG_INFORMATION2
|
||||
*
|
||||
* This function decodes the LEG INFORMATION2 facility
|
||||
* The datas will be copied in the some Asterisk channel variables -> see README.qsig
|
||||
*
|
||||
* parameters
|
||||
* invoke struct, which contains encoded data from facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* nothing
|
||||
*/
|
||||
void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
|
||||
{
|
||||
|
||||
unsigned int datalength;
|
||||
unsigned int seqlength = 0;
|
||||
int myidx = 0;
|
||||
|
||||
unsigned int parameter = 0;
|
||||
unsigned int divCount = 0;
|
||||
unsigned int divReason = 0;
|
||||
unsigned int orgDivReason = 0;
|
||||
char tempstr[5];
|
||||
char divertNum[ASN197ADE_NUMDIGITS_STRSIZE+1];
|
||||
char origCalledNum[ASN197ADE_NUMDIGITS_STRSIZE+1];
|
||||
struct asn197ade_numberscreened divertPNS, origPNS;
|
||||
char divertName[ASN197NO_NAME_STRSIZE+1];
|
||||
char origCalledName[ASN197NO_NAME_STRSIZE+1];
|
||||
unsigned int temp = 0;
|
||||
unsigned int temp2 = 0;
|
||||
|
||||
divertNum[0] = 0;
|
||||
origCalledNum[0] = 0;
|
||||
divertNum[0] = 0;
|
||||
divertName[0] = 0;
|
||||
origCalledName[0] = 0;
|
||||
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling QSIG LEG INFO2 (id# %#x)\n", invoke->id);
|
||||
|
||||
origPNS.partyNumber = NULL;
|
||||
divertPNS.partyNumber = NULL;
|
||||
|
||||
if (invoke->data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
|
||||
/* We do not handle this, because it should start with an sequence tag */
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - not a sequence\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This facility is encoded as SEQUENCE */
|
||||
seqlength = invoke->data[myidx++];
|
||||
datalength = invoke->datalen;
|
||||
if (datalength < (seqlength+1)) {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG LEG INFO2 - buffer error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (invoke->data[myidx++] == ASN1_INTEGER)
|
||||
divCount = cc_qsig_asn1_get_integer(invoke->data, &myidx);
|
||||
|
||||
if (invoke->data[myidx++] == ASN1_ENUMERATED)
|
||||
divReason = cc_qsig_asn1_get_integer(invoke->data, &myidx);
|
||||
|
||||
while (myidx < datalength) {
|
||||
parameter = (invoke->data[myidx++] & 0x0f);
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * Found parameter %i\n", parameter);
|
||||
switch (parameter) {
|
||||
case 0:
|
||||
myidx++; /* Ignore Length of enumeration tag*/
|
||||
if (invoke->data[myidx++] == ASN1_ENUMERATED)
|
||||
orgDivReason = cc_qsig_asn1_get_integer(invoke->data, &myidx);
|
||||
break;
|
||||
case 1:
|
||||
temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */
|
||||
cc_qsig_asn197ade_get_pns(invoke->data, &myidx, &divertPNS);
|
||||
myidx += temp;
|
||||
break;
|
||||
case 2:
|
||||
temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */
|
||||
cc_qsig_asn197ade_get_pns(invoke->data, &myidx, &origPNS);
|
||||
myidx += temp;
|
||||
break;
|
||||
case 3:
|
||||
/* Redirecting Name */
|
||||
temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */
|
||||
cc_qsig_asn197no_get_name(divertName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data);
|
||||
myidx += temp + 1;
|
||||
break;
|
||||
case 4:
|
||||
/* origCalled Name */
|
||||
temp = invoke->data[myidx++]; /* keep the length of this info - maybe we don't get all data now */
|
||||
cc_qsig_asn197no_get_name(origCalledName, ASN197NO_NAME_STRSIZE, &temp2, &myidx, invoke->data);
|
||||
myidx += temp + 1;
|
||||
break;
|
||||
default:
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * unknown parameter %i\n", parameter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(tempstr, 5, "%i", divReason);
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVREASON", tempstr);
|
||||
snprintf(tempstr, 5, "%i", orgDivReason);
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVREASON", tempstr);
|
||||
snprintf(tempstr, 5, "%i", divCount);
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVCOUNT", tempstr);
|
||||
|
||||
if (divertPNS.partyNumber)
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNUM", divertPNS.partyNumber);
|
||||
if (origPNS.partyNumber)
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNUM", origPNS.partyNumber);
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_DIVNAME", divertName);
|
||||
pbx_builtin_setvar_helper(i->owner, "_QSIG_LI2_ODIVNAME", origCalledName);
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG_LEG_INFO2: %i(%i), %ix %s->%s, %s->%s\n", divReason, orgDivReason, divCount, origPNS.partyNumber, divertPNS.partyNumber, origCalledName, divertName);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.12 ECMA/ISDN/CALLTRANSFER
|
||||
*
|
||||
* This function encodes the call transfer facility
|
||||
*
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* param is parameter from capicommand
|
||||
* info this facility is part of 2, 0 is facility 1, 1 is facility 2
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param, int info)
|
||||
{
|
||||
char *cid, *ccanswer;
|
||||
char *name = NULL;
|
||||
int icanswer = 0;
|
||||
int cidlen = 0;
|
||||
int namelength = 0;
|
||||
int seqlen = 13;
|
||||
char c[255];
|
||||
int ix = 0;
|
||||
|
||||
if (param) { /* got Call Transfer Parameters */
|
||||
if (info) {
|
||||
cid = strsep(¶m, COMMANDSEPARATOR);
|
||||
cidlen = strlen(cid);
|
||||
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
|
||||
cidlen = 20;
|
||||
} else {
|
||||
char *tmp = strsep(¶m, COMMANDSEPARATOR);
|
||||
tmp = NULL;
|
||||
cid = strsep(¶m, COMMANDSEPARATOR);
|
||||
cidlen = strlen(cid);
|
||||
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
|
||||
cidlen = 20;
|
||||
|
||||
ccanswer = strsep(¶m, COMMANDSEPARATOR);
|
||||
if (ccanswer[0])
|
||||
icanswer = ccanswer[0] - 0x30;
|
||||
}
|
||||
} else {
|
||||
/* cid = ast_strdup(i->owner->cid.cid_num);*/ /* Here we get the Asterisk extension */
|
||||
if (info) { /* info is >0 on outbound channel (second facility) */
|
||||
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
|
||||
|
||||
cid = ast_strdup(i->cid);
|
||||
cidlen = strlen(cid);
|
||||
|
||||
if (ii) {
|
||||
/* send callers name to user B */
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
if (ast_channel_caller(ii->owner)->id.name.valid ) {
|
||||
name = ast_strdupa(S_COR(ast_channel_caller(ii->owner)->id.name.valid, ast_channel_caller(ii->owner)->id.name.str, ""));
|
||||
namelength = strlen(name);
|
||||
}
|
||||
#elif defined(CC_AST_HAS_VERSION_1_8)
|
||||
if (ii->owner->caller.id.name.valid ) {
|
||||
name = ast_strdupa(S_COR(ii->owner->caller.id.name.valid, ii->owner->caller.id.name.str, ""));
|
||||
namelength = strlen(name);
|
||||
}
|
||||
#else /* !(defined(CC_AST_HAS_VERSION_11_0) || defined(CC_AST_HAS_VERSION_1_8)) */
|
||||
if (ii->owner->cid.cid_name) {
|
||||
name = ast_strdupa(ii->owner->cid.cid_name);
|
||||
namelength = strlen(name);
|
||||
}
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) || defined(CC_AST_HAS_VERSION_1_8) */
|
||||
}
|
||||
} else { /* have to build first facility - send destination number back to inbound channel */
|
||||
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
|
||||
cid = ast_strdup(ii->dnid);
|
||||
cidlen = strlen(cid);
|
||||
|
||||
if (ii) {
|
||||
/* send destination name to user A */
|
||||
if (ii->qsig_data.dnameid) {
|
||||
name = ast_strdupa(ii->qsig_data.dnameid);
|
||||
namelength = strlen(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!info)
|
||||
icanswer = i->qsig_data.calltransfer_onring % 1;
|
||||
}
|
||||
|
||||
seqlen += cidlen;
|
||||
if (namelength)
|
||||
seqlen += 4 + namelength;
|
||||
|
||||
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
|
||||
c[ix++] = seqlen;
|
||||
|
||||
c[ix++] = ASN1_ENUMERATED; /* End Designation */
|
||||
c[ix++] = 1; /* length */
|
||||
c[ix++] = info;
|
||||
|
||||
c[ix++] = (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED) + 0; /* val 0 - Source Caller ID struct */
|
||||
c[ix++] = 5 + cidlen;
|
||||
c[ix++] = ASN1_TC_CONTEXTSPEC; /* CallerID */
|
||||
c[ix++] = cidlen;
|
||||
memcpy(&c[ix], cid, cidlen);
|
||||
ix += cidlen;
|
||||
c[ix++] = ASN1_ENUMERATED; /* Screening Indicator */
|
||||
c[ix++] = 1; /* length */
|
||||
c[ix++] = 1; /* 01 = userProvidedVerifiedAndPassed ...we hope so */
|
||||
|
||||
{
|
||||
if (namelength) {
|
||||
c[ix++] = (ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED) + 1; /* val 1 - Source Caller ID struct */
|
||||
c[ix++] = 2 + namelength;
|
||||
c[ix++] = ASN1_OCTETSTRING; /* CallerID */
|
||||
c[ix++] = namelength;
|
||||
memcpy(&c[ix], name, namelength);
|
||||
ix += namelength;
|
||||
}
|
||||
}
|
||||
|
||||
c[ix++] = ASN1_ENUMERATED; /* val 3 - wait for connect ? */
|
||||
c[ix++] = 1;
|
||||
c[ix++] = icanswer;
|
||||
|
||||
/* end of SEQUENCE */
|
||||
/* there are optional data possible here */
|
||||
|
||||
invoke->id = 12;
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = 12; /* Invoke Operation Code */
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_CT: %i->%s\n", info, cid);
|
||||
|
||||
if (cid)
|
||||
ast_free(cid);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode Operation: 1.3.12.9.12 ECMA/ISDN/CALLTRANSFER
|
||||
*
|
||||
* This function decodes the call transfer facility
|
||||
*
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data from facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* transfer to destination number
|
||||
*/
|
||||
unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, struct capi_pvt *i, struct cc_qsig_ctcomplete *ctc)
|
||||
{
|
||||
unsigned int datalength;
|
||||
unsigned int seqlength = 0;
|
||||
unsigned char *data = invoke->data;
|
||||
int myidx = 0;
|
||||
/* TODO: write more code */
|
||||
|
||||
char *ct_status_txt[] = { "ANSWERED", "ALERTING" };
|
||||
char ct_name[ASN197NO_NAME_STRSIZE+1] = { "EMPTY" };
|
||||
unsigned int namelength = 0;
|
||||
int temp = 0;
|
||||
|
||||
ctc->endDesignation = primaryEnd;
|
||||
ctc->redirectionNumber.partyNumber = NULL;
|
||||
ctc->redirectionNumber.screeningInd = userProvidedNotScreened;
|
||||
ctc->basicCallInfoElements = NULL;
|
||||
ctc->redirectionName = NULL;
|
||||
ctc->callStatus = answered;
|
||||
ctc->argumentExtension = NULL; /* unhandled yet */
|
||||
|
||||
#define ct_err(x...) { cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG CALL TRANSFER - "x); return 0; }
|
||||
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling QSIG CALL TRANSFER (id# %#x)\n", invoke->id);
|
||||
|
||||
if (data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
|
||||
/* We do not handle this, because it should start with an sequence tag */
|
||||
ct_err("not a sequence\n");
|
||||
}
|
||||
|
||||
/* This facility is encoded as SEQUENCE */
|
||||
seqlength = data[myidx++];
|
||||
datalength = invoke->datalen;
|
||||
if (datalength < (seqlength+1)) {
|
||||
ct_err("buffer error\n");
|
||||
}
|
||||
|
||||
if (data[myidx++] == ASN1_ENUMERATED) {
|
||||
ctc->endDesignation = cc_qsig_asn1_get_integer(data, &myidx);
|
||||
} else {
|
||||
ct_err("no endDesignation information.\n");
|
||||
}
|
||||
|
||||
temp = cc_qsig_asn197ade_get_pns(data, &myidx, &ctc->redirectionNumber);
|
||||
|
||||
if (!temp) {
|
||||
ct_err("error on decoding PresentedNumberScreened value.\n");
|
||||
}
|
||||
myidx += temp;
|
||||
|
||||
if (myidx < datalength) {
|
||||
if (data[myidx] == ASN1_TC_APPLICATION) {
|
||||
myidx++;
|
||||
/* TODO: check size -> could be bigger than 256 bytes - MSB is set then */
|
||||
ctc->basicCallInfoElements = ast_malloc(data[myidx]);
|
||||
if (ctc->basicCallInfoElements) {
|
||||
memcpy(ctc->basicCallInfoElements, &data[myidx+1], data[myidx] );
|
||||
} else {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * QSIG CALL TRANSFER - couldn't allocate memory for basicCallInfoElements.\n", (int)data[myidx]);
|
||||
}
|
||||
myidx += data[myidx] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (myidx < datalength) {
|
||||
if (data[myidx] != ASN1_ENUMERATED) { /* Maybe we get an name (OPTIONAL) */
|
||||
myidx += cc_qsig_asn197no_get_name(ct_name, ASN197NO_NAME_STRSIZE+1, &namelength, &myidx, data );
|
||||
if (namelength)
|
||||
ctc->redirectionName = ast_strdup(ct_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (myidx < datalength) {
|
||||
if (data[myidx++] == ASN1_ENUMERATED) { /* Call Status */
|
||||
ctc->callStatus = cc_qsig_asn1_get_integer(data, &myidx);
|
||||
}
|
||||
}
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG CALL TRANSFER endDesignation: %i partyNumber: %s (ScreeningInd: %i), partyName: \"%s\", Call state: %s\n",
|
||||
ctc->endDesignation, ctc->redirectionNumber.partyNumber, ctc->redirectionNumber.screeningInd, ctc->redirectionName, ct_status_txt[ctc->callStatus]);
|
||||
|
||||
return 1;
|
||||
#undef ct_err
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.99 ECMA/ISDN/SINGLESTEPCALLTRANSFER
|
||||
*
|
||||
* This function encodes the single step call transfer facility
|
||||
*
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* param is parameter from capicommand
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
|
||||
{
|
||||
char *cidsrc, *ciddst;
|
||||
int srclen, dstlen;
|
||||
int seqlen = 12;
|
||||
char c[255];
|
||||
int ix = 0;
|
||||
|
||||
cidsrc = strsep(¶m, COMMANDSEPARATOR);
|
||||
srclen = strlen(cidsrc);
|
||||
if (srclen > 20) /* HACK: stop action here, maybe we have invalid data */
|
||||
srclen = 20;
|
||||
|
||||
ciddst = strsep(¶m, COMMANDSEPARATOR);
|
||||
dstlen = strlen(ciddst);
|
||||
if (dstlen > 20) /* HACK: stop action here, maybe we have invalid data */
|
||||
dstlen = 20;
|
||||
|
||||
seqlen += srclen + dstlen;
|
||||
|
||||
|
||||
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
|
||||
c[ix++] = seqlen;
|
||||
|
||||
c[ix++] = ASN1_TC_CONTEXTSPEC; /* val 1 - Destination CallerID */
|
||||
c[ix++] = dstlen;
|
||||
memcpy(&c[ix], ciddst, dstlen);
|
||||
ix += dstlen;
|
||||
|
||||
c[ix++] = ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED; /* val 2 - Source Caller ID struct */
|
||||
c[ix++] = 5 + srclen;
|
||||
c[ix++] = ASN1_TC_CONTEXTSPEC; /* CallerID */
|
||||
c[ix++] = srclen;
|
||||
memcpy(&c[ix], cidsrc, srclen);
|
||||
ix += srclen;
|
||||
c[ix++] = ASN1_ENUMERATED; /* Screening Indicator */
|
||||
c[ix++] = 1; /* length */
|
||||
c[ix++] = 1; /* 01 = userProvidedVerifiedAndPassed ...we hope so */
|
||||
|
||||
c[ix++] = ASN1_BOOLEAN; /* val 3 - wait for connect ? */
|
||||
c[ix++] = 1;
|
||||
c[ix++] = 0;
|
||||
|
||||
/* end of SEQUENCE */
|
||||
/* there are optional data possible here */
|
||||
|
||||
invoke->id = 99;
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = 99;
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_SSCT: %s->%s\n", cidsrc, ciddst);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle Operation: 1.3.12.9.19 ECMA/ISDN/PATH REPLACEMENT PROPOSE
|
||||
*
|
||||
* This function decodes the PATH REPLACEMENT PROPOSE facility
|
||||
* The datas will be copied in the some capi_pvt channel variables
|
||||
*
|
||||
* parameters
|
||||
* invoke struct, which contains encoded data from facility
|
||||
* i is pointer to capi channel
|
||||
* returns
|
||||
* nothing
|
||||
*/
|
||||
void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
|
||||
{
|
||||
|
||||
unsigned int datalength;
|
||||
unsigned int seqlength = 0;
|
||||
int myidx = 0;
|
||||
/* TODO: write more code */
|
||||
|
||||
char callid[4+1];
|
||||
char reroutingnr[ASN197ADE_NUMDIGITS_STRSIZE+1];
|
||||
int temp = 0;
|
||||
|
||||
callid[0] = 0;
|
||||
reroutingnr[0] = 0;
|
||||
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 "Handling QSIG PATH REPLACEMENT PROPOSE (id# %#x)\n", invoke->id);
|
||||
|
||||
if (invoke->data[myidx++] != (ASN1_SEQUENCE | ASN1_TC_UNIVERSAL | ASN1_TF_CONSTRUCTED)) { /* 0x30 */
|
||||
/* We do not handle this, because it should start with an sequence tag */
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - not a sequence\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This facility is encoded as SEQUENCE */
|
||||
seqlength = invoke->data[myidx++];
|
||||
datalength = invoke->datalen;
|
||||
if (datalength < (seqlength+1)) {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - buffer error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (invoke->data[myidx++] == ASN1_NUMERICSTRING) {
|
||||
int strsize;
|
||||
strsize = cc_qsig_asn1_get_string((unsigned char*)&callid, sizeof(callid), &invoke->data[myidx]);
|
||||
myidx += strsize +1;
|
||||
} else {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - NUMERICSTRING expected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (invoke->data[myidx++] == ASN1_TC_CONTEXTSPEC)
|
||||
temp = cc_qsig_asn1_get_string((unsigned char*)&reroutingnr, sizeof(reroutingnr), &invoke->data[myidx]);
|
||||
|
||||
if (temp) {
|
||||
myidx += temp;
|
||||
} else {
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * not Handling QSIG REPLACEMENT PROPOSE - partyNumber expected (%i)\n", myidx);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
i->qsig_data.pr_propose_cid = ast_strdup(callid);
|
||||
i->qsig_data.pr_propose_pn = ast_strdup(reroutingnr);
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Got QSIG_PATHREPLACEMENT_PROPOSE Call identity: %s, Party number: %s (%i)\n", callid, reroutingnr, temp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode Operation: 1.3.12.9.19 ECMA/ISDN/PATH REPLACEMENT PROPOSE
|
||||
*
|
||||
* This function encodes the path replacement propose
|
||||
*
|
||||
* We create an invoke struct with the complete encoded invoke.
|
||||
*
|
||||
* parameters
|
||||
* buf is pointer to facility array, not used now
|
||||
* idx current idx in facility array, not used now
|
||||
* invoke struct, which contains encoded data for facility
|
||||
* i is pointer to capi channel
|
||||
* param is parameter from capicommand
|
||||
* returns
|
||||
* always 0
|
||||
*/
|
||||
void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
|
||||
{
|
||||
int invokeop = 4;
|
||||
|
||||
char *callid, *reroutingnr;
|
||||
int cidlen, rrnlen;
|
||||
int seqlen = 4;
|
||||
char c[255];
|
||||
int ix = 0;
|
||||
|
||||
int res = 0;
|
||||
int ii = 0;
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
int compsp = 0;
|
||||
|
||||
if (!i->qsig_data.pr_propose_cid)
|
||||
return ;
|
||||
|
||||
if (!i->qsig_data.pr_propose_pn)
|
||||
return ;
|
||||
|
||||
callid = i->qsig_data.pr_propose_cid;
|
||||
reroutingnr = i->qsig_data.pr_propose_pn;
|
||||
|
||||
cidlen = strlen(callid);
|
||||
rrnlen = strlen(reroutingnr);
|
||||
seqlen += cidlen + rrnlen;
|
||||
|
||||
|
||||
#if 0
|
||||
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
|
||||
c[ix++] = seqlen;
|
||||
|
||||
c[ix++] = ASN1_NUMERICSTRING; /* val 1 - CallID */
|
||||
c[ix++] = cidlen;
|
||||
memcpy(&c[ix], callid, cidlen);
|
||||
ix += cidlen;
|
||||
|
||||
c[ix++] = ASN1_TC_CONTEXTSPEC; /* val 2 - Rerouting number*/
|
||||
c[ix++] = rrnlen;
|
||||
memcpy(&c[ix], reroutingnr, rrnlen);
|
||||
ix += rrnlen;
|
||||
#else
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED), c, ii);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
res = cc_qsig_asn1_add_string2(ASN1_NUMERICSTRING, &c[ii], sizeof(c) - ii, 20, callid, cidlen);
|
||||
if (res < 0)
|
||||
return;
|
||||
ii += res;
|
||||
|
||||
res = cc_qsig_asn1_add_string2(ASN1_TC_CONTEXTSPEC, &c[ii], sizeof(c) - ii, 20, reroutingnr, rrnlen);
|
||||
if (res < 0)
|
||||
return;
|
||||
ii += res;
|
||||
|
||||
ASN1_FIXUP(compstk, compsp, c, ii);
|
||||
ix = ii;
|
||||
#endif
|
||||
|
||||
/* end of SEQUENCE */
|
||||
/* there are optional data possible here */
|
||||
|
||||
invoke->id = invokeop;
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = invokeop;
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
|
||||
cc_qsig_verbose( 0, VERBOSE_PREFIX_4 " * Sending QSIG_PATHREPLACEMENT_PROPOSE: Call identity: %s, Party number: %s\n", callid, reroutingnr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cc_qsig_encode_ecma_ccnr_req(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
|
||||
{
|
||||
int invokeop = 27;
|
||||
|
||||
int ii = 0;
|
||||
unsigned char c[256];
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
int compsp = 0;
|
||||
int ix = 0;
|
||||
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_TF_CONSTRUCTED | ASN1_SEQUENCE), c, ii);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
|
||||
|
||||
#if 0 /* Constructed data - ECMAv1 HICOM/HIPATH */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
res = asn1_string_encode(ASN1_OCTETSTRING, &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
i += res;
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
#endif
|
||||
|
||||
invoke->id = invokeop;
|
||||
invoke->descr_type = -1;
|
||||
invoke->type = invokeop;
|
||||
|
||||
invoke->datalen = ix;
|
||||
memcpy(invoke->data, c, ix);
|
||||
cc_qsig_verbose( 1, VERBOSE_PREFIX_4 " * Sending QSIG_CCNR_REQ\n");
|
||||
|
||||
return ;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* (QSIG)
|
||||
*
|
||||
* Implementation of QSIG extensions for chan_capi
|
||||
*
|
||||
* Copyright 2006-2007 (c) Mario Goegel
|
||||
*
|
||||
* Mario Goegel <m.goegel@gmx.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include "chan_capi_qsig_asn197ade.h"
|
||||
|
||||
#ifndef PBX_QSIG_ECMA_H
|
||||
#define PBX_QSIG_ECMA_H
|
||||
|
||||
/* ECMA Features structs */
|
||||
|
||||
|
||||
/* Call Transfer Complete struct */
|
||||
struct cc_qsig_ctcomplete {
|
||||
enum {
|
||||
primaryEnd, /* 0 */
|
||||
secondaryEnd /* 1 */
|
||||
} endDesignation;
|
||||
|
||||
struct asn197ade_numberscreened redirectionNumber;
|
||||
char *basicCallInfoElements; /* OPTIONAL: ASN1_APPLICATION Type */
|
||||
char *redirectionName; /* OPTIONAL */
|
||||
enum {
|
||||
answered,
|
||||
alerting
|
||||
} callStatus; /* DEFAULT: answered */
|
||||
char *argumentExtension; /* OPTIONAL: ASN1_SEQUENCE - manufacturer specific extension */
|
||||
};
|
||||
|
||||
/* CCBS struct */
|
||||
struct cc_qsig_ccbsreq {
|
||||
char *numberA; /* Simplified numbers*/
|
||||
char *numberB;
|
||||
char *PSS1InfoElement; /* Bearer caps, LLC, HLC */
|
||||
char *subaddrA;
|
||||
char *subaddrB;
|
||||
int can_retain_service;
|
||||
int retain_sig_connection;
|
||||
char *extension;
|
||||
};
|
||||
|
||||
/*
|
||||
*** ECMA QSIG Functions
|
||||
*/
|
||||
|
||||
extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype, const char *name);
|
||||
|
||||
extern int cc_qsig_encode_ecma_isdn_leginfo3_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *name);
|
||||
|
||||
extern void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
|
||||
extern void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
|
||||
extern void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param);
|
||||
|
||||
extern void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param);
|
||||
|
||||
extern void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param, int info);
|
||||
extern unsigned int cc_qsig_decode_ecma_calltransfer(struct cc_qsig_invokedata *invoke, struct capi_pvt *i, struct cc_qsig_ctcomplete *ctc);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_rtp.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
||||
/* RTP settings / NCPI RTP struct */
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_alaw[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len Ulaw Alaw */
|
||||
"\x04\x00\x00\x08\x08"
|
||||
/* Len Alaw */
|
||||
"\x02\x08\x08"
|
||||
/* Len UlawLen Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x00\x04\x03\x00\xa0\x00\x08\x04\x03\x00\xa0\x00";
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_ulaw[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len Ulaw Alaw */
|
||||
"\x04\x00\x00\x08\x08"
|
||||
/* Len Ulaw */
|
||||
"\x02\x00\x00"
|
||||
/* Len UlawLen Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x00\x04\x03\x00\xa0\x00\x08\x04\x03\x00\xa0\x00";
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_gsm[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len GSM Alaw */
|
||||
"\x04\x03\x03\x08\x08"
|
||||
/* Len GSM */
|
||||
"\x02\x03\x03"
|
||||
/* Len GSM Len Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x03\x04\x0f\x00\xa0\x00\x08\x04\x00\x00\xa0\x00";
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_g723[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len G723 Alaw */
|
||||
"\x04\x04\x04\x08\x08"
|
||||
/* Len G723 */
|
||||
"\x02\x04\x04"
|
||||
/* Len G723Len Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x04\x04\x01\x00\xa0\x00\x08\x04\x00\x00\xa0\x00";
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_g726[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len G726 Alaw */
|
||||
"\x04\x02\x02\x08\x08"
|
||||
/* Len G726 */
|
||||
"\x02\x02\x02"
|
||||
/* Len G726Len Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x02\x04\x0f\x00\xa0\x00\x08\x04\x00\x00\xa0\x00";
|
||||
|
||||
static unsigned char NCPI_voice_over_ip_g729[] =
|
||||
/* Len Options */
|
||||
"\x27\x00\x00\x00\x00"
|
||||
/* Len Filt */
|
||||
"\x00"
|
||||
/* Len Tem PT Seq Timestamp SSRC */
|
||||
"\x0c\x80\x00\x00\x00\x00\x00\x00\x00\x12\x34\x56\x78"
|
||||
/* Len G729 Alaw */
|
||||
"\x04\x12\x12\x08\x08"
|
||||
/* Len G729 */
|
||||
"\x02\x12\x12"
|
||||
/* Len G729Len Opts IntervalAlawLen Opts Interval */
|
||||
"\x0c\x12\x04\x0f\x00\xa0\x00\x08\x04\x00\x00\xa0\x00";
|
||||
|
||||
|
||||
/*
|
||||
* return NCPI for chosen RTP codec
|
||||
*/
|
||||
_cstruct capi_rtp_ncpi(struct capi_pvt *i)
|
||||
{
|
||||
_cstruct ncpi = NULL;
|
||||
|
||||
if ((i) && (i->owner) &&
|
||||
(i->bproto == CC_BPROTO_RTP)) {
|
||||
switch(i->codec) {
|
||||
case CC_FORMAT_ALAW:
|
||||
ncpi = NCPI_voice_over_ip_alaw;
|
||||
break;
|
||||
case CC_FORMAT_ULAW:
|
||||
ncpi = NCPI_voice_over_ip_ulaw;
|
||||
break;
|
||||
case CC_FORMAT_GSM:
|
||||
ncpi = NCPI_voice_over_ip_gsm;
|
||||
break;
|
||||
case CC_FORMAT_G723_1:
|
||||
ncpi = NCPI_voice_over_ip_g723;
|
||||
break;
|
||||
case CC_FORMAT_G726:
|
||||
ncpi = NCPI_voice_over_ip_g726;
|
||||
break;
|
||||
case CC_FORMAT_G729A:
|
||||
ncpi = NCPI_voice_over_ip_g729;
|
||||
break;
|
||||
default:
|
||||
cc_log(LOG_ERROR, "%s: format %s(%d) invalid.\n",
|
||||
i->vname, cc_getformatname(i->codec), i->codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ncpi;
|
||||
}
|
||||
|
||||
/*
|
||||
* create rtp for capi interface
|
||||
*/
|
||||
int capi_alloc_rtp(struct capi_pvt *i)
|
||||
{
|
||||
#ifndef CC_AST_HAS_VERSION_10_0 /* Use vocoder without RTP framing */
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
struct ast_sockaddr addr;
|
||||
struct ast_sockaddr us;
|
||||
#else
|
||||
struct ast_hostent ahp;
|
||||
struct hostent *hp;
|
||||
struct in_addr addr;
|
||||
struct sockaddr_in us;
|
||||
#endif
|
||||
#ifndef CC_AST_HAS_VERSION_1_4
|
||||
char temp[MAXHOSTNAMELEN];
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
ast_sockaddr_parse(&addr, "localhost:0", 0);
|
||||
#else
|
||||
hp = ast_gethostbyname("localhost", &ahp);
|
||||
memcpy(&addr, hp->h_addr, sizeof(addr));
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
i->rtp = ast_rtp_instance_new(NULL, NULL, &addr, NULL);
|
||||
#else
|
||||
i->rtp = ast_rtp_instance_new(NULL, NULL, (struct sockaddr_in *)&addr, NULL);
|
||||
#endif
|
||||
#else
|
||||
i->rtp = ast_rtp_new_with_bindaddr(NULL, NULL, 0, 0, addr);
|
||||
#endif
|
||||
|
||||
if (!(i->rtp)) {
|
||||
cc_log(LOG_ERROR, "%s: unable to alloc rtp.\n", i->vname);
|
||||
return 1;
|
||||
}
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
ast_rtp_instance_get_local_address(i->rtp, &us);
|
||||
ast_rtp_instance_set_remote_address(i->rtp, &us);
|
||||
#else
|
||||
ast_rtp_get_us(i->rtp, &us);
|
||||
ast_rtp_set_peer(i->rtp, &us);
|
||||
#endif
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_4 "%s: alloc rtp socket on %s:%d\n",
|
||||
i->vname,
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
ast_sockaddr_stringify(&us), ntohs(ast_sockaddr_port(&us)));
|
||||
#else
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
ast_inet_ntoa(us.sin_addr),
|
||||
#else
|
||||
ast_inet_ntoa(temp, sizeof(temp), us.sin_addr),
|
||||
#endif
|
||||
ntohs(us.sin_port));
|
||||
#endif
|
||||
i->timestamp = 0;
|
||||
return 0;
|
||||
#else
|
||||
i->rtp = 0;
|
||||
cc_log(LOG_ERROR, "%s: use vocoder\n", i->vname);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* write rtp for a channel
|
||||
*/
|
||||
int capi_write_rtp(struct capi_pvt *i, struct ast_frame *f)
|
||||
{
|
||||
#ifndef CC_AST_HAS_VERSION_10_0 /* Use vocoder */
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
struct ast_sockaddr us;
|
||||
#else
|
||||
struct sockaddr_in us;
|
||||
socklen_t uslen = sizeof(us);
|
||||
#endif
|
||||
int len;
|
||||
unsigned int *rtpheader;
|
||||
unsigned char buf[256];
|
||||
|
||||
if (!(i->rtp)) {
|
||||
cc_log(LOG_ERROR, "rtp struct is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
ast_rtp_instance_get_local_address(i->rtp, &us);
|
||||
ast_rtp_instance_set_remote_address(i->rtp, &us);
|
||||
if (ast_rtp_instance_write(i->rtp, f) != 0) {
|
||||
#else
|
||||
ast_rtp_get_us(i->rtp, &us);
|
||||
ast_rtp_set_peer(i->rtp, &us);
|
||||
if (ast_rtp_write(i->rtp, f) != 0) {
|
||||
#endif
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: rtp_write error, dropping packet.\n",
|
||||
i->vname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
len = ast_recvfrom(ast_rtp_instance_fd(i->rtp, 0), buf, sizeof(buf), 0, &us);
|
||||
#else
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
len = recvfrom(ast_rtp_instance_fd(i->rtp, 0),
|
||||
buf, sizeof(buf), 0, (struct sockaddr *)&us, &uslen);
|
||||
#else
|
||||
len = recvfrom(ast_rtp_fd(i->rtp),
|
||||
buf, sizeof(buf), 0, (struct sockaddr *)&us, &uslen);
|
||||
#endif
|
||||
#endif
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
rtpheader = (unsigned int *)buf;
|
||||
|
||||
rtpheader[1] = htonl(i->timestamp);
|
||||
i->timestamp += CAPI_MAX_B3_BLOCK_SIZE;
|
||||
|
||||
if (len > (CAPI_MAX_B3_BLOCK_SIZE + RTP_HEADER_SIZE)) {
|
||||
cc_verbose(4, 0, VERBOSE_PREFIX_4 "%s: rtp write data: frame too big (len = %d).\n",
|
||||
i->vname, len);
|
||||
continue;
|
||||
}
|
||||
if (i->B3count >= CAPI_MAX_B3_BLOCKS) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_4 "%s: B3count is full, dropping packet.\n",
|
||||
i->vname);
|
||||
continue;
|
||||
}
|
||||
cc_mutex_lock(&i->lock);
|
||||
i->B3count++;
|
||||
cc_mutex_unlock(&i->lock);
|
||||
|
||||
i->send_buffer_handle++;
|
||||
|
||||
cc_verbose(6, 1, VERBOSE_PREFIX_4 "%s: RTP write for NCCI=%#x len=%d(%d) %s ts=%x\n",
|
||||
i->vname, i->NCCI, len, f->datalen, cc_getformatname(GET_FRAME_SUBCLASS_CODEC(f->subclass)),
|
||||
i->timestamp);
|
||||
|
||||
capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
|
||||
"dwww",
|
||||
buf,
|
||||
len,
|
||||
i->send_buffer_handle,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* read data b3 in RTP mode
|
||||
*/
|
||||
struct ast_frame *capi_read_rtp(struct capi_pvt *i, unsigned char *buf, int len)
|
||||
{
|
||||
#ifndef CC_AST_HAS_VERSION_10_0 /* Use vocoder */
|
||||
struct ast_frame *f;
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
struct ast_sockaddr us;
|
||||
#else
|
||||
struct sockaddr_in us;
|
||||
#endif
|
||||
|
||||
if (!(i->owner))
|
||||
return NULL;
|
||||
|
||||
if (!(i->rtp)) {
|
||||
cc_log(LOG_ERROR, "rtp struct is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
ast_rtp_instance_get_local_address(i->rtp, &us);
|
||||
ast_rtp_instance_set_remote_address(i->rtp, &us);
|
||||
#else
|
||||
ast_rtp_get_us(i->rtp, &us);
|
||||
ast_rtp_set_peer(i->rtp, &us);
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_AST_SOCKADDR
|
||||
if (len != ast_sendto(ast_rtp_instance_fd(i->rtp, 0), buf, len, 0, &us))
|
||||
#else
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
if (len != sendto(ast_rtp_instance_fd(i->rtp, 0), buf, len, 0, (struct sockaddr *)&us, sizeof(us)))
|
||||
#else
|
||||
if (len != sendto(ast_rtp_fd(i->rtp), buf, len, 0, (struct sockaddr *)&us, sizeof(us)))
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
cc_verbose(4, 1, VERBOSE_PREFIX_3 "%s: RTP sendto error\n",
|
||||
i->vname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_RTP_ENGINE_H
|
||||
if ((f = ast_rtp_instance_read(i->rtp, 0))) {
|
||||
#else
|
||||
if ((f = ast_rtp_read(i->rtp))) {
|
||||
#endif
|
||||
if (f->frametype != AST_FRAME_VOICE) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: DATA_B3_IND RTP (len=%d) non voice type=%d\n",
|
||||
i->vname, len, f->frametype);
|
||||
return NULL;
|
||||
}
|
||||
cc_verbose(6, 1, VERBOSE_PREFIX_4 "%s: DATA_B3_IND RTP NCCI=%#x len=%d %s (read/write=%d/%d)\n",
|
||||
i->vname, i->NCCI, len, cc_getformatname(GET_FRAME_SUBCLASS_CODEC(f->subclass)),
|
||||
i->owner->readformat, i->owner->writeformat);
|
||||
if (i->owner->nativeformats != GET_FRAME_SUBCLASS_CODEC(f->subclass)) {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: DATA_B3_IND RTP nativeformats=%d, but subclass=%ld\n",
|
||||
i->vname, i->owner->nativeformats, GET_FRAME_SUBCLASS_CODEC(f->subclass));
|
||||
i->owner->nativeformats = GET_FRAME_SUBCLASS_CODEC(f->subclass);
|
||||
ast_set_read_format(i->owner, i->owner->readformat);
|
||||
ast_set_write_format(i->owner, i->owner->writeformat);
|
||||
}
|
||||
}
|
||||
return f;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* eval RTP profile
|
||||
*/
|
||||
void voice_over_ip_profile(struct cc_capi_controller *cp)
|
||||
{
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cmsg CMSG;
|
||||
struct timeval tv;
|
||||
unsigned char fac[4] = "\x03\x02\x00\x00";
|
||||
int waitcount = 200;
|
||||
unsigned short info = 0;
|
||||
unsigned int payload1, payload2;
|
||||
|
||||
capi_sendf(NULL, 0, CAPI_FACILITY_REQ, cp->controller, get_capi_MessageNumber(),
|
||||
"ws",
|
||||
FACILITYSELECTOR_VOICE_OVER_IP,
|
||||
&fac
|
||||
);
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
while (waitcount) {
|
||||
error = capi20_waitformessage(capi_ApplID, &tv);
|
||||
error = capi_get_cmsg(&CMSG, capi_ApplID);
|
||||
if (error == 0) {
|
||||
if (IS_FACILITY_CONF(&CMSG)) {
|
||||
info = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
usleep(20000);
|
||||
waitcount--;
|
||||
}
|
||||
if (!info) {
|
||||
cc_log(LOG_WARNING, "did not receive FACILITY_CONF\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* parse profile */
|
||||
if (FACILITY_CONF_FACILITYSELECTOR(&CMSG) != FACILITYSELECTOR_VOICE_OVER_IP) {
|
||||
cc_log(LOG_WARNING, "unexpected FACILITY_SELECTOR = %#x\n",
|
||||
FACILITY_CONF_FACILITYSELECTOR(&CMSG));
|
||||
return;
|
||||
}
|
||||
if ((info = FACILITY_CONF_INFO(&CMSG)) != 0x0000) {
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_4 "FACILITY_CONF INFO = %#x, RTP not used.\n",
|
||||
info);
|
||||
return;
|
||||
|
||||
}
|
||||
if (FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[0] < 13) {
|
||||
cc_log(LOG_WARNING, "conf parameter too short %d, RTP not used.\n",
|
||||
FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[0]);
|
||||
return;
|
||||
}
|
||||
info = read_capi_word(&(FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[1]));
|
||||
if (info != 0x0002) {
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_4 "FACILITY_CONF wrong parameter (0x%04x), RTP not used.\n",
|
||||
info);
|
||||
return;
|
||||
}
|
||||
info = read_capi_word(&(FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[4]));
|
||||
payload1 = read_capi_dword(&(FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[6]));
|
||||
payload2 = read_capi_dword(&(FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(&CMSG)[10]));
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_4 "RTP payload options 0x%04x 0x%08x 0x%08x\n",
|
||||
info, payload1, payload2);
|
||||
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_4 "RTP codec: ");
|
||||
if (payload1 & 0x00000100) {
|
||||
cp->rtpcodec |= CC_FORMAT_ALAW;
|
||||
cc_verbose(3, 0, "G.711-alaw ");
|
||||
}
|
||||
if (payload1 & 0x00000001) {
|
||||
cp->rtpcodec |= CC_FORMAT_ULAW;
|
||||
cc_verbose(3, 0, "G.711-ulaw ");
|
||||
}
|
||||
if (payload1 & 0x00000008) {
|
||||
cp->rtpcodec |= CC_FORMAT_GSM;
|
||||
cc_verbose(3, 0, "GSM ");
|
||||
}
|
||||
if (payload1 & 0x00000010) {
|
||||
cp->rtpcodec |= CC_FORMAT_G723_1;
|
||||
cc_verbose(3, 0, "G.723.1 ");
|
||||
}
|
||||
if (payload1 & 0x00000004) {
|
||||
cp->rtpcodec |= CC_FORMAT_G726;
|
||||
cc_verbose(3, 0, "G.726 ");
|
||||
}
|
||||
if (payload1 & 0x00040000) {
|
||||
cp->rtpcodec |= CC_FORMAT_G729A;
|
||||
cc_verbose(3, 0, "G.729 ");
|
||||
}
|
||||
if (payload1 & (1U << 27)) {
|
||||
cp->rtpcodec |= CC_FORMAT_ILBC;
|
||||
cc_verbose(3, 0, "iLBC ");
|
||||
}
|
||||
#ifdef CC_FORMAT_G722
|
||||
if (payload1 & (1U << 9)) {
|
||||
cp->rtpcodec |= CC_FORMAT_G722;
|
||||
cc_verbose(3, 0, "G.722 ");
|
||||
}
|
||||
#endif
|
||||
#if defined(CC_FORMAT_SIREN7) && defined(CC_FORMAT_SIREN14)
|
||||
if (payload1 & (1U << 24)) {
|
||||
#ifdef CC_FORMAT_SIREN7
|
||||
cp->rtpcodec |= CC_FORMAT_SIREN7;
|
||||
cc_verbose(3, 0, "siren7 ");
|
||||
#endif
|
||||
#ifdef CC_FORMAT_SIREN14
|
||||
cp->rtpcodec |= CC_FORMAT_SIREN14;
|
||||
cc_verbose(3, 0, "siren14 ");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(CC_FORMAT_SLINEAR) || defined(CC_FORMAT_SLINEAR16)
|
||||
if (payload1 & (1U << 1)) {
|
||||
#if defined(CC_FORMAT_SLINEAR)
|
||||
cp->rtpcodec |= CC_FORMAT_SLINEAR;
|
||||
cc_verbose(3, 0, "slin ");
|
||||
#endif
|
||||
#if defined(CC_FORMAT_SLINEAR16)
|
||||
cp->rtpcodec |= CC_FORMAT_SLINEAR16;
|
||||
cc_verbose(3, 0, "slin16 ");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
cc_verbose(3, 0, "\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _PBX_CAPI_RTP_H
|
||||
#define _PBX_CAPI_RTP_H
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern int capi_alloc_rtp(struct capi_pvt *i);
|
||||
extern void voice_over_ip_profile(struct cc_capi_controller *cp);
|
||||
extern int capi_write_rtp(struct capi_pvt *i, struct ast_frame *f);
|
||||
extern struct ast_frame *capi_read_rtp(struct capi_pvt *i, unsigned char *buf, int len);
|
||||
extern _cstruct capi_rtp_ncpi(struct capi_pvt *i);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,983 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2005-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_supplementary.h"
|
||||
#include "chan_capi_utils.h"
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
#include <asterisk/event.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define CCBSNR_TYPE_CCBS 1
|
||||
#define CCBSNR_TYPE_CCNR 2
|
||||
|
||||
#define CCBSNR_AVAILABLE 1
|
||||
#define CCBSNR_REQUESTED 2
|
||||
#define CCBSNR_ACTIVATED 3
|
||||
|
||||
struct ccbsnr_s {
|
||||
char type;
|
||||
_cword id;
|
||||
unsigned int plci;
|
||||
unsigned int state;
|
||||
unsigned int handle;
|
||||
_cword mode;
|
||||
_cword rbref;
|
||||
char partybusy;
|
||||
char context[AST_MAX_CONTEXT];
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
int priority;
|
||||
time_t age;
|
||||
struct ccbsnr_s *next;
|
||||
};
|
||||
|
||||
static struct ccbsnr_s *ccbsnr_list = NULL;
|
||||
AST_MUTEX_DEFINE_STATIC(ccbsnr_lock);
|
||||
|
||||
/*
|
||||
* remove too old CCBS/CCNR entries
|
||||
* (must be called with ccbsnr_lock held)
|
||||
*/
|
||||
static void del_old_ccbsnr(void)
|
||||
{
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
struct ccbsnr_s *tmp = NULL;
|
||||
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if ((ccbsnr->age + 86400) < time(NULL)) {
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
|
||||
": CCBS/CCNR handle=%d timeout.\n", ccbsnr->handle);
|
||||
if (!tmp) {
|
||||
ccbsnr_list = ccbsnr->next;
|
||||
} else {
|
||||
tmp->next = ccbsnr->next;
|
||||
}
|
||||
ast_free(ccbsnr);
|
||||
break;
|
||||
}
|
||||
tmp = ccbsnr;
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup CCBS/CCNR ids
|
||||
*/
|
||||
void cleanup_ccbsnr(void)
|
||||
{
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
struct ccbsnr_s *tmp = NULL;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
tmp = ccbsnr;
|
||||
ccbsnr = ccbsnr->next;
|
||||
ast_free(tmp);
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* return the controller of ccbsnr handle
|
||||
*/
|
||||
unsigned int capi_get_ccbsnrcontroller(unsigned int handle)
|
||||
{
|
||||
unsigned int contr = 0;
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (ccbsnr->handle == handle) {
|
||||
contr = (ccbsnr->plci & 0xff);
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
return contr;
|
||||
}
|
||||
|
||||
/*
|
||||
* a new CCBS/CCNR id was received
|
||||
*/
|
||||
static void new_ccbsnr_id(char type, unsigned int plci,
|
||||
_cword id, struct capi_pvt *i)
|
||||
{
|
||||
char buffer[CAPI_MAX_STRING];
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
|
||||
ccbsnr = ast_malloc(sizeof(struct ccbsnr_s));
|
||||
if (ccbsnr == NULL) {
|
||||
cc_log(LOG_ERROR, "Unable to allocate CCBS/CCNR struct.\n");
|
||||
return;
|
||||
}
|
||||
memset(ccbsnr, 0, sizeof(struct ccbsnr_s));
|
||||
|
||||
ccbsnr->age = time(NULL);
|
||||
ccbsnr->type = type;
|
||||
ccbsnr->id = id;
|
||||
ccbsnr->rbref = 0xdead;
|
||||
ccbsnr->plci = plci;
|
||||
ccbsnr->state = CCBSNR_AVAILABLE;
|
||||
ccbsnr->handle = (id | ((plci & 0xff) << 16) | (type << 28));
|
||||
|
||||
if (i->peer) {
|
||||
snprintf(buffer, CAPI_MAX_STRING-1, "%u", ccbsnr->handle);
|
||||
pbx_builtin_setvar_helper(i->peer, "CCLINKAGEID", buffer);
|
||||
} else {
|
||||
cc_log(LOG_NOTICE, "No peerlink found to set CCBS/CCNR linkage ID.\n");
|
||||
}
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
del_old_ccbsnr();
|
||||
ccbsnr->next = ccbsnr_list;
|
||||
ccbsnr_list = ccbsnr;
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3
|
||||
"%s: PLCI=%#x CCBS/CCNR new id=0x%04x handle=%d\n",
|
||||
i->vname, plci, id, ccbsnr->handle);
|
||||
|
||||
/* if the hangup frame was deferred, it can be done now and here */
|
||||
if (i->whentoqueuehangup) {
|
||||
i->whentoqueuehangup = 0;
|
||||
capi_queue_cause_control(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* return the pointer to ccbsnr structure by handle
|
||||
*/
|
||||
static struct ccbsnr_s *get_ccbsnr_link(char type, unsigned int plci,
|
||||
unsigned int handle, _cword ref, unsigned int *state, char *busy)
|
||||
{
|
||||
struct ccbsnr_s *ret;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ret = ccbsnr_list;
|
||||
while (ret) {
|
||||
if (((handle) && (ret->handle == handle)) ||
|
||||
((ref != 0xffff) && (ret->rbref == ref) &&
|
||||
(ret->type == type) && ((ret->plci & 0xff) == (plci & 0xff)))) {
|
||||
if (state) {
|
||||
*state = ret->state;
|
||||
}
|
||||
if (busy) {
|
||||
*busy = ret->partybusy;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ret = ret->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* function to tell if CCBSNR is activated
|
||||
*/
|
||||
static int ccbsnr_tell_activated(void *data)
|
||||
{
|
||||
unsigned int handle = (unsigned int)(unsigned long)data;
|
||||
int ret = 0;
|
||||
unsigned int state;
|
||||
|
||||
if (get_ccbsnr_link(0, 0, handle, 0xffff, &state, NULL) != NULL) {
|
||||
if (state == CCBSNR_REQUESTED) {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* select CCBS/CCNR id
|
||||
*/
|
||||
static unsigned int select_ccbsnr_id(unsigned int id, char type,
|
||||
char *context, char *exten, int priority)
|
||||
{
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
int ret = 0;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (((ccbsnr->plci & 0xff) == ((id >> 16) & 0xff)) &&
|
||||
(ccbsnr->id == (id & 0xffff)) &&
|
||||
(ccbsnr->type == type) &&
|
||||
(ccbsnr->state == CCBSNR_AVAILABLE)) {
|
||||
strncpy(ccbsnr->context, context, sizeof(ccbsnr->context) - 1);
|
||||
strncpy(ccbsnr->exten, exten, sizeof(ccbsnr->exten) - 1);
|
||||
ccbsnr->priority = priority;
|
||||
ccbsnr->state = CCBSNR_REQUESTED;
|
||||
ret = ccbsnr->handle;
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
|
||||
": request CCBS/NR id=0x%x handle=%d (%s,%s,%d)\n",
|
||||
id, ret, context, exten, priority);
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* a CCBS/CCNR ref was removed
|
||||
*/
|
||||
static void del_ccbsnr_ref(unsigned int plci, _cword ref)
|
||||
{
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
struct ccbsnr_s *tmp = NULL;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (((ccbsnr->plci & 0xff) == (plci & 0xff)) &&
|
||||
(ccbsnr->rbref == ref)) {
|
||||
if (!tmp) {
|
||||
ccbsnr_list = ccbsnr->next;
|
||||
} else {
|
||||
tmp->next = ccbsnr->next;
|
||||
}
|
||||
ast_free(ccbsnr);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
|
||||
": PLCI=%#x CCBS/CCNR removed ref=0x%04x\n", plci, ref);
|
||||
break;
|
||||
}
|
||||
tmp = ccbsnr;
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* return rbref of CCBS/CCNR and delete entry
|
||||
*/
|
||||
_cword capi_ccbsnr_take_ref(unsigned int handle)
|
||||
{
|
||||
unsigned int plci = 0;
|
||||
_cword rbref = 0xdead;
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (ccbsnr->handle == handle) {
|
||||
plci = ccbsnr->plci;
|
||||
rbref = ccbsnr->rbref;
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
if (rbref != 0xdead) {
|
||||
del_ccbsnr_ref(plci, rbref);
|
||||
}
|
||||
|
||||
return rbref;
|
||||
}
|
||||
|
||||
/*
|
||||
* a CCBS/CCNR id was removed
|
||||
*/
|
||||
static void del_ccbsnr_id(unsigned int plci, _cword id)
|
||||
{
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
struct ccbsnr_s *tmp = NULL;
|
||||
unsigned int oldstate;
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (((ccbsnr->plci & 0xff) == (plci & 0xff)) &&
|
||||
(ccbsnr->id == id)) {
|
||||
oldstate = ccbsnr->state;
|
||||
if (ccbsnr->state == CCBSNR_AVAILABLE) {
|
||||
if (!tmp) {
|
||||
ccbsnr_list = ccbsnr->next;
|
||||
} else {
|
||||
tmp->next = ccbsnr->next;
|
||||
}
|
||||
ast_free(ccbsnr);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME ": PLCI=%#x CCBS/CCNR removed "
|
||||
"id=0x%04x state=%d\n", plci, id, oldstate);
|
||||
} else {
|
||||
/* just deactivate the linkage id */
|
||||
ccbsnr->id = 0xdead;
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME ": PLCI=%#x CCBS/CCNR erase-only "
|
||||
"id=0x%04x state=%d\n", plci, id, ccbsnr->state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
tmp = ccbsnr;
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* on an activated CCBS, the remote party is now free
|
||||
*/
|
||||
static void ccbsnr_remote_user_free(_cmsg *CMSG, char type, unsigned int PLCI, _cword rbref)
|
||||
{
|
||||
struct ast_channel *c;
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
char handlename[CAPI_MAX_STRING];
|
||||
int state = AST_STATE_DOWN;
|
||||
|
||||
/* XXX start alerting , when answered use CCBS call */
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if ((ccbsnr->type == type) &&
|
||||
((ccbsnr->plci & 0xff) == (PLCI & 0xff)) &&
|
||||
(ccbsnr->rbref == rbref)) {
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
if (!(ccbsnr)) {
|
||||
cc_log(LOG_ERROR, CC_MESSAGE_NAME " CCBS/CCBR reference not found!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(handlename, CAPI_MAX_STRING-1, "%u", ccbsnr->handle);
|
||||
|
||||
#ifdef CC_AST_HAS_EXT_CHAN_ALLOC
|
||||
c = ast_channel_alloc(0, state, handlename, NULL,
|
||||
#ifdef CC_AST_HAS_EXT2_CHAN_ALLOC
|
||||
0, ccbsnr->exten, ccbsnr->context,
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
NULL, NULL,
|
||||
#endif
|
||||
#ifdef CC_AST_HAS_LINKEDID_CHAN_ALLOC
|
||||
NULL,
|
||||
#endif
|
||||
0,
|
||||
#endif
|
||||
"CCBSNR/%x", ccbsnr->handle);
|
||||
#else
|
||||
c = ast_channel_alloc(0);
|
||||
#endif
|
||||
|
||||
if (c == NULL) {
|
||||
cc_log(LOG_ERROR, "Unable to allocate channel!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CC_AST_HAS_EXT_CHAN_ALLOC
|
||||
#ifdef CC_AST_HAS_STRINGFIELD_IN_CHANNEL
|
||||
ast_string_field_build(c, name, "CCBSNR/%x", ccbsnr->handle);
|
||||
#else
|
||||
snprintf(c->name, sizeof(c->name) - 1, "CCBSNR/%x",
|
||||
ccbsnr->handle);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef CC_AST_HAS_VERSION_1_4
|
||||
c->type = "CCBS/CCNR";
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
ast_channel_priority_set(c, ccbsnr->priority);
|
||||
#else /* !defined(CC_AST_HAS_VERSION_11_0) */
|
||||
c->priority = ccbsnr->priority;
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) */
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_11_0
|
||||
/*! \todo verify if necessary/complete */
|
||||
ast_channel_connected(c)->id.number.valid = 1;
|
||||
ast_free (ast_channel_connected(c)->id.number.str);
|
||||
ast_channel_connected(c)->id.number.str = ast_strdup(handlename);
|
||||
|
||||
ast_free (ast_channel_dialed(c)->number.str);
|
||||
ast_channel_dialed(c)->number.str = ast_strdup (ccbsnr->exten);
|
||||
#elif defined(CC_AST_HAS_VERSION_1_8)
|
||||
/*! \todo verify if necessary/complete */
|
||||
c->connected.id.number.valid = 1;
|
||||
ast_free (c->connected.id.number.str);
|
||||
c->connected.id.number.str = ast_strdup(handlename);
|
||||
|
||||
ast_free (c->dialed.number.str);
|
||||
c->dialed.number.str = ast_strdup (ccbsnr->exten);
|
||||
#else /* !(defined(CC_AST_HAS_VERSION_11_0) || defined(CC_AST_HAS_VERSION_1_8)) */
|
||||
if (c->cid.cid_num) {
|
||||
ast_free(c->cid.cid_num);
|
||||
}
|
||||
c->cid.cid_num = ast_strdup(handlename);
|
||||
if (c->cid.cid_dnid) {
|
||||
ast_free(c->cid.cid_dnid);
|
||||
}
|
||||
c->cid.cid_dnid = ast_strdup(ccbsnr->exten);
|
||||
#endif /* defined(CC_AST_HAS_VERSION_11_0) || defined(CC_AST_HAS_VERSION_1_8) */
|
||||
|
||||
#ifndef CC_AST_HAS_EXT2_CHAN_ALLOC
|
||||
cc_copy_string(c->context, ccbsnr->context, sizeof(c->context));
|
||||
cc_copy_string(c->exten, ccbsnr->exten, sizeof(c->exten));
|
||||
#endif
|
||||
|
||||
#ifndef CC_AST_HAS_EXT_CHAN_ALLOC
|
||||
ast_setstate(c, state);
|
||||
#endif
|
||||
|
||||
if (ast_pbx_start(c)) {
|
||||
cc_log(LOG_ERROR, CC_MESSAGE_NAME " CCBS/CCNR: Unable to start pbx!\n");
|
||||
} else {
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_2 "contr%d: started PBX for CCBS/CCNR callback (%s/%s/%d)\n",
|
||||
PLCI & 0xff, ccbsnr->context, ccbsnr->exten, ccbsnr->priority);
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_13_0
|
||||
ast_channel_unlock(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* send Listen for supplementary to specified controller
|
||||
*/
|
||||
void ListenOnSupplementary(unsigned controller)
|
||||
{
|
||||
_cmsg CMSG;
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
int waitcount = 50;
|
||||
|
||||
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, controller, get_capi_MessageNumber(),
|
||||
"w(w(d))",
|
||||
FACILITYSELECTOR_SUPPLEMENTARY,
|
||||
0x0001, /* LISTEN */
|
||||
0x0000079f
|
||||
);
|
||||
|
||||
while (waitcount) {
|
||||
error = capidev_check_wait_get_cmsg(&CMSG);
|
||||
|
||||
if (IS_FACILITY_CONF(&CMSG)) {
|
||||
break;
|
||||
}
|
||||
usleep(30000);
|
||||
waitcount--;
|
||||
}
|
||||
if (!waitcount) {
|
||||
cc_log(LOG_ERROR,"Unable to supplementary-listen on contr%d (error=0x%x)\n",
|
||||
controller, error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CAPI FACILITY_IND supplementary services
|
||||
*/
|
||||
int handle_facility_indication_supplementary(
|
||||
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i)
|
||||
{
|
||||
_cword function;
|
||||
_cword infoword = 0xffff;
|
||||
unsigned char length;
|
||||
_cdword handle;
|
||||
_cword mode;
|
||||
_cword rbref;
|
||||
struct ccbsnr_s *ccbsnrlink;
|
||||
char partybusy = 0;
|
||||
int ret = 0;
|
||||
|
||||
function = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[1]);
|
||||
length = FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[3];
|
||||
|
||||
if (length >= 2) {
|
||||
infoword = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4]);
|
||||
}
|
||||
|
||||
/* first check functions without interface needed */
|
||||
switch (function) {
|
||||
case 0x000f: /* CCBS request */
|
||||
handle = read_capi_dword(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
mode = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[10]);
|
||||
rbref = read_capi_dword(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[12]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS request reason=0x%04x "
|
||||
"handle=%d mode=0x%x rbref=0x%x\n",
|
||||
PLCI & 0xff, PLCI, infoword, handle, mode, rbref);
|
||||
show_capi_info(NULL, infoword);
|
||||
if ((ccbsnrlink = get_ccbsnr_link(0, 0, handle, 0xffff, NULL, NULL)) == NULL) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME " ccbs request indication without request!\n");
|
||||
break;
|
||||
}
|
||||
if (infoword == 0) {
|
||||
/* success */
|
||||
ccbsnrlink->state = CCBSNR_ACTIVATED;
|
||||
ccbsnrlink->rbref = rbref;
|
||||
ccbsnrlink->mode = mode;
|
||||
} else {
|
||||
/* error */
|
||||
ccbsnrlink->state = CCBSNR_AVAILABLE;
|
||||
}
|
||||
break;
|
||||
case 0x0010: /* CCBS deactivate */
|
||||
handle = read_capi_dword(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS deactivate handle=0x%x reason=0x%x\n",
|
||||
PLCI & 0xff, PLCI, handle, infoword);
|
||||
show_capi_info(NULL, infoword);
|
||||
if ((ccbsnrlink = get_ccbsnr_link(0, 0, handle, 0xffff, NULL, NULL)) == NULL) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME " ccbs deactivate indication without request!\n");
|
||||
break;
|
||||
}
|
||||
if (infoword == 0) {
|
||||
/* success */
|
||||
ccbsnrlink->state = CCBSNR_AVAILABLE;
|
||||
ccbsnrlink->rbref = 0xdead;
|
||||
ccbsnrlink->id = 0xdead;
|
||||
ccbsnrlink->mode = 0;
|
||||
}
|
||||
break;
|
||||
case 0x800d: /* CCBS erase call linkage ID */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS/CCNR erase id=0x%04x\n",
|
||||
PLCI & 0xff, PLCI, infoword);
|
||||
del_ccbsnr_id(PLCI, infoword);
|
||||
break;
|
||||
case 0x800e: /* CCBS status */
|
||||
rbref = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS status ref=0x%04x mode=0x%x\n",
|
||||
PLCI & 0xff, PLCI, rbref, infoword);
|
||||
if (get_ccbsnr_link(CCBSNR_TYPE_CCBS, PLCI, 0, rbref, NULL, &partybusy) == NULL) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME " CCBS status reference not found!\n");
|
||||
}
|
||||
capi_sendf(NULL, 0, CAPI_FACILITY_RESP, PLCI, HEADER_MSGNUM(CMSG),
|
||||
"w(w(w))",
|
||||
FACILITYSELECTOR_SUPPLEMENTARY,
|
||||
0x800e, /* CCBS status */
|
||||
(partybusy) ? 0x0000 : 0x0001
|
||||
);
|
||||
ret = 1;
|
||||
break;
|
||||
case 0x800f: /* CCBS remote user free */
|
||||
rbref = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS remote user free ref=0x%04x mode=0x%x\n",
|
||||
PLCI & 0xff, PLCI, rbref, infoword);
|
||||
ccbsnr_remote_user_free(CMSG, CCBSNR_TYPE_CCBS, PLCI, rbref);
|
||||
break;
|
||||
case 0x8010: /* CCBS B-free */
|
||||
rbref = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS B-free ref=0x%04x mode=0x%x\n",
|
||||
PLCI & 0xff, PLCI, rbref, infoword);
|
||||
break;
|
||||
case 0x8011: /* CCBS erase (ref), deactivated by network */
|
||||
rbref = read_capi_word(&FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[6]);
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS deactivate ref=0x%04x mode=0x%x\n",
|
||||
PLCI & 0xff, PLCI, rbref, infoword);
|
||||
del_ccbsnr_ref(PLCI, rbref);
|
||||
break;
|
||||
case 0x8012: /* CCBS stop alerting */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "contr%d: PLCI=%#x CCBS B-free ref=0x%04x\n",
|
||||
PLCI & 0xff, PLCI, infoword);
|
||||
break;
|
||||
case 0x8014: {/* MWI indication, stateless */
|
||||
const unsigned char* info = &FACILITY_IND_FACILITYINDICATIONPARAMETER(CMSG)[4];
|
||||
unsigned short basicService = read_capi_word(info); info += 2;
|
||||
unsigned int numberOfMessages = read_capi_dword(info); info += 4;
|
||||
unsigned short messageStatus = read_capi_word(info); info += 2;
|
||||
unsigned short messageReference = read_capi_word(info); info += 2;
|
||||
char controllingUserNumberName[AST_MAX_EXTENSION];
|
||||
char controllingUserProvidedNumberName[AST_MAX_EXTENSION];
|
||||
char mwiTimeName[AST_MAX_EXTENSION];
|
||||
char mailboxName[AST_MAX_EXTENSION];
|
||||
|
||||
if (info[0] > 3) {
|
||||
memcpy(controllingUserNumberName,
|
||||
&info[4],
|
||||
MIN(AST_MAX_EXTENSION-1, info[0] - 3));
|
||||
controllingUserNumberName[MIN(AST_MAX_EXTENSION-1, info[0] - 3)] = 0;
|
||||
} else {
|
||||
controllingUserNumberName[0] = 0;
|
||||
}
|
||||
info += info[0] + 1;
|
||||
|
||||
if (info[0] > 3) {
|
||||
memcpy(controllingUserProvidedNumberName,
|
||||
&info[4],
|
||||
MIN(AST_MAX_EXTENSION-1, info[0] - 3));
|
||||
controllingUserProvidedNumberName[MIN(AST_MAX_EXTENSION-1, info[0] - 3)] = 0;
|
||||
} else {
|
||||
controllingUserProvidedNumberName[0] = 0;
|
||||
}
|
||||
info += info[0] + 1;
|
||||
|
||||
if (info[0] != 0) {
|
||||
memcpy(mwiTimeName, &info[1], MIN(AST_MAX_EXTENSION-1, info[0]));
|
||||
mwiTimeName[MIN(AST_MAX_EXTENSION-1, info[0])] = 0;
|
||||
} else {
|
||||
mwiTimeName[0] = 0;
|
||||
}
|
||||
info += info[0] + 1;
|
||||
|
||||
if (info[0] > 1) {
|
||||
memcpy(mailboxName, &info[2], MIN(AST_MAX_EXTENSION-1, info[0]));
|
||||
mailboxName[MIN(AST_MAX_EXTENSION-1, info[0]-1)] = 0;
|
||||
} else {
|
||||
mailboxName[0] = 0;
|
||||
}
|
||||
|
||||
if (messageStatus == 0 || messageStatus == 1) {
|
||||
cc_verbose(4, 0, VERBOSE_PREFIX_4 "CAPI%u Rx MWI %s for '%s@CAPI_Remote %s %s time '%s' %d messages ref %d service %d\n",
|
||||
PLCI & 0xff,
|
||||
messageStatus == 0 ? "add" : "del", mailboxName, controllingUserNumberName, controllingUserProvidedNumberName,
|
||||
mwiTimeName, numberOfMessages, messageReference, basicService);
|
||||
if (messageStatus == 0 && mailboxName[0] != 0) {
|
||||
#if defined(CC_AST_HAS_EVENT_MWI)
|
||||
struct ast_event *event;
|
||||
|
||||
if ((event = ast_event_new(AST_EVENT_MWI,
|
||||
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailboxName,
|
||||
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "CAPI_Remote",
|
||||
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, MAX(1,numberOfMessages),
|
||||
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, 0,
|
||||
AST_EVENT_IE_END))) {
|
||||
ast_event_queue_and_cache(event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
cc_verbose(4, 0, VERBOSE_PREFIX_1 "CAPI%u Rx MWI %s for '%s@default %s %s time '%s' service %d\n",
|
||||
messageStatus == 0 ? "add" : "del", mailboxName, controllingUserNumberName, controllingUserProvidedNumberName,
|
||||
mwiTimeName, basicService);
|
||||
}
|
||||
} return ret;
|
||||
case 0x8000: /* Hold notification */
|
||||
if ((i->isdnstate & CAPI_ISDN_STATE_EC) != 0) {
|
||||
cc_verbose(4, 0, VERBOSE_PREFIX_1 "%s: EC reset\n", i->vname);
|
||||
capi_echo_canceller(i, EC_FUNCTION_DISABLE);
|
||||
capi_echo_canceller(i, EC_FUNCTION_ENABLE);
|
||||
}
|
||||
return ret;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!i) {
|
||||
cc_verbose(4, 1, "CAPI: FACILITY_IND SUPPLEMENTARY "
|
||||
"no interface for PLCI=%#x\n", PLCI);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* now functions bound to interface */
|
||||
switch (function) {
|
||||
case 0x0002: /* HOLD */
|
||||
if (infoword != 0) {
|
||||
/* reason != 0x0000 == problem */
|
||||
i->onholdPLCI = 0;
|
||||
i->isdnstate &= ~CAPI_ISDN_STATE_HOLD;
|
||||
cc_log(LOG_WARNING, "%s: unable to put PLCI=%#x onhold, REASON = 0x%04x, maybe you need to subscribe for this...\n",
|
||||
i->vname, PLCI, infoword);
|
||||
show_capi_info(i, infoword);
|
||||
} else {
|
||||
/* reason = 0x0000 == call on hold */
|
||||
i->state = CAPI_STATE_ONHOLD;
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x put onhold\n",
|
||||
i->vname, PLCI);
|
||||
}
|
||||
break;
|
||||
case 0x0003: /* RETRIEVE */
|
||||
if (infoword != 0) {
|
||||
cc_log(LOG_WARNING, "%s: unable to retrieve PLCI=%#x, REASON = 0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
show_capi_info(i, infoword);
|
||||
} else {
|
||||
i->state = CAPI_STATE_CONNECTED;
|
||||
i->PLCI = i->onholdPLCI;
|
||||
i->onholdPLCI = 0;
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x retrieved\n",
|
||||
i->vname, PLCI);
|
||||
cc_start_b3(i);
|
||||
}
|
||||
break;
|
||||
case 0x0006: /* ECT */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x ECT Reason=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
if (infoword != 0) {
|
||||
i->isdnstate &= ~CAPI_ISDN_STATE_ECT;
|
||||
}
|
||||
show_capi_info(i, infoword);
|
||||
break;
|
||||
case 0x0007: /* 3PTY begin */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x 3PTY begin Reason=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
show_capi_info(i, infoword);
|
||||
break;
|
||||
case 0x0008: /* 3PTY end */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x 3PTY end Reason=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
show_capi_info(i, infoword);
|
||||
break;
|
||||
case 0x000d: /* CD */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CD Service Reason=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
show_capi_info(i, infoword);
|
||||
break;
|
||||
case 0x8013: /* CCBS info retain */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCBS unique id=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
new_ccbsnr_id(CCBSNR_TYPE_CCBS, PLCI, infoword, i);
|
||||
break;
|
||||
case 0x8015: /* CCNR info retain */
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 "%s: PLCI=%#x CCNR unique id=0x%04x\n",
|
||||
i->vname, PLCI, infoword);
|
||||
new_ccbsnr_id(CCBSNR_TYPE_CCNR, PLCI, infoword, i);
|
||||
break;
|
||||
case 0x000e: /* CCBS status */
|
||||
case 0x000f: /* CCBS request */
|
||||
case 0x800f: /* CCBS remote user free */
|
||||
case 0x800d: /* CCBS erase call linkage ID */
|
||||
case 0x8010: /* CCBS B-free */
|
||||
case 0x8011: /* CCBS erase (ref), deactivated by network */
|
||||
case 0x8012: /* CCBS stop alerting */
|
||||
/* handled above */
|
||||
break;
|
||||
default:
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: unhandled FACILITY_IND supplementary function %04x\n",
|
||||
i->vname, function);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CAPI FACILITY_CONF supplementary
|
||||
*/
|
||||
void handle_facility_confirmation_supplementary(
|
||||
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i, struct ast_channel** interface_owner)
|
||||
{
|
||||
_cword function;
|
||||
_cword serviceinfo;
|
||||
char name[64];
|
||||
|
||||
if (*i) {
|
||||
strncpy(name, (*i)->vname, sizeof(name) - 1);
|
||||
} else {
|
||||
snprintf(name, sizeof(name) - 1, "contr%d", PLCI & 0xff);
|
||||
}
|
||||
|
||||
function = read_capi_word(&FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[1]);
|
||||
serviceinfo = read_capi_word(&FACILITY_CONF_FACILITYCONFIRMATIONPARAMETER(CMSG)[4]);
|
||||
|
||||
switch(function) {
|
||||
case 0x0002: /* HOLD */
|
||||
if (serviceinfo == 0) {
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_3 "%s: Call on hold (PLCI=%#x)\n",
|
||||
name, PLCI);
|
||||
}
|
||||
break;
|
||||
case 0x0003: /* RETRIEVE */
|
||||
if (serviceinfo == 0) {
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_3 "%s: Call retreived (PLCI=%#x)\n",
|
||||
name, PLCI);
|
||||
}
|
||||
break;
|
||||
case 0x0006: /* ECT */
|
||||
if (serviceinfo == 0) {
|
||||
cc_verbose(2, 0, VERBOSE_PREFIX_3 "%s: ECT confirmed (PLCI=%#x)\n",
|
||||
name, PLCI);
|
||||
}
|
||||
break;
|
||||
case 0x000d: /* CD */
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_3 "%s: CD confirmation (0x%04x) (PLCI=%#x)\n",
|
||||
name, serviceinfo, PLCI);
|
||||
break;
|
||||
case 0x000f: /* CCBS request */
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_3 "%s: CCBS request confirmation (0x%04x) (PLCI=%#x)\n",
|
||||
name, serviceinfo, PLCI);
|
||||
break;
|
||||
case 0x0012: /* CCBS call */
|
||||
cc_verbose(2, 1, VERBOSE_PREFIX_3 "%s: CCBS call confirmation (0x%04x) (PLCI=%#x)\n",
|
||||
name, serviceinfo, PLCI);
|
||||
capidev_handle_connection_conf(i, PLCI, FACILITY_CONF_INFO(CMSG), HEADER_MSGNUM(CMSG), interface_owner);
|
||||
break;
|
||||
default:
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: unhandled FACILITY_CONF supplementary function %04x\n",
|
||||
name, function);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* capicommand 'ccpartybusy'
|
||||
*/
|
||||
int pbx_capi_ccpartybusy(struct ast_channel *c, char *data)
|
||||
{
|
||||
char *slinkageid, *yesno;
|
||||
unsigned int linkid = 0;
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
char partybusy = 0;
|
||||
|
||||
slinkageid = strsep(&data, COMMANDSEPARATOR);
|
||||
yesno = data;
|
||||
|
||||
if (slinkageid) {
|
||||
linkid = (unsigned int)strtoul(slinkageid, NULL, 0);
|
||||
}
|
||||
|
||||
if ((yesno) && ast_true(yesno)) {
|
||||
partybusy = 1;
|
||||
}
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (((ccbsnr->plci & 0xff) == ((linkid >> 16) & 0xff)) &&
|
||||
(ccbsnr->id == (linkid & 0xffff))) {
|
||||
ccbsnr->partybusy = partybusy;
|
||||
cc_verbose(1, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
|
||||
": CCBS/NR id=0x%x busy set to %d\n", linkid, partybusy);
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* capicommand 'ccbsstop'
|
||||
*/
|
||||
int pbx_capi_ccbsstop(struct ast_channel *c, char *data)
|
||||
{
|
||||
char *slinkageid;
|
||||
unsigned int linkid = 0;
|
||||
unsigned int handle = 0;
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
_cword ref = 0xdead;
|
||||
struct ccbsnr_s *ccbsnr;
|
||||
|
||||
slinkageid = data;
|
||||
|
||||
if (slinkageid) {
|
||||
linkid = (unsigned int)strtoul(slinkageid, NULL, 0);
|
||||
}
|
||||
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME " ccbsstop: '%d'\n",
|
||||
linkid);
|
||||
|
||||
cc_mutex_lock(&ccbsnr_lock);
|
||||
ccbsnr = ccbsnr_list;
|
||||
while (ccbsnr) {
|
||||
if (((ccbsnr->plci & 0xff) == ((linkid >> 16) & 0xff)) &&
|
||||
(ccbsnr->id == (linkid & 0xffff)) &&
|
||||
(ccbsnr->type == CCBSNR_TYPE_CCBS) &&
|
||||
(ccbsnr->state == CCBSNR_ACTIVATED)) {
|
||||
ref = ccbsnr->rbref;
|
||||
handle = ccbsnr->handle;
|
||||
break;
|
||||
}
|
||||
ccbsnr = ccbsnr->next;
|
||||
}
|
||||
cc_mutex_unlock(&ccbsnr_lock);
|
||||
|
||||
if (ref != 0xdead) {
|
||||
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, (linkid >> 16) & 0xff,
|
||||
get_capi_MessageNumber(),
|
||||
"w(w(dw))",
|
||||
FACILITYSELECTOR_SUPPLEMENTARY,
|
||||
0x0010, /* CCBS deactivate */
|
||||
handle, /* handle */
|
||||
ref /* CCBS reference */
|
||||
);
|
||||
} else {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3, CC_MESSAGE_NAME
|
||||
" ccbsstop: linkid %d not found in table.\n", linkid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* capicommand 'ccbs'
|
||||
*/
|
||||
int pbx_capi_ccbs(struct ast_channel *c, char *data)
|
||||
{
|
||||
char *slinkageid, *context, *exten, *priority;
|
||||
unsigned int linkid = 0;
|
||||
unsigned int handle, a;
|
||||
char *result = "ERROR";
|
||||
char *goodresult = "ACTIVATED";
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
unsigned int ccbsnrstate;
|
||||
|
||||
slinkageid = strsep(&data, COMMANDSEPARATOR);
|
||||
context = strsep(&data, COMMANDSEPARATOR);
|
||||
exten = strsep(&data, COMMANDSEPARATOR);
|
||||
priority = data;
|
||||
|
||||
if (slinkageid) {
|
||||
linkid = (unsigned int)strtoul(slinkageid, NULL, 0);
|
||||
}
|
||||
|
||||
if ((!context) || (!exten) || (!priority)) {
|
||||
cc_log(LOG_WARNING, CC_MESSAGE_NAME
|
||||
" ccbs requires <context>|<exten>|<priority>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3 CC_MESSAGE_NAME
|
||||
" ccbs: '%d' '%s' '%s' '%s'\n",
|
||||
linkid, context, exten, priority);
|
||||
|
||||
handle = select_ccbsnr_id(linkid, CCBSNR_TYPE_CCBS,
|
||||
context, exten, (int)strtol(priority, NULL, 0));
|
||||
|
||||
if (handle > 0) {
|
||||
error = capi_sendf(NULL, 0, CAPI_FACILITY_REQ, (linkid >> 16) & 0xff,
|
||||
get_capi_MessageNumber(),
|
||||
"w(w(dw))",
|
||||
FACILITYSELECTOR_SUPPLEMENTARY,
|
||||
0x000f, /* CCBS request */
|
||||
handle, /* handle */
|
||||
(linkid & 0xffff) /* CCBS linkage ID */
|
||||
);
|
||||
|
||||
for (a = 0; a < 7; a++) {
|
||||
/* Wait for CCBS request indication */
|
||||
if (ast_safe_sleep_conditional(c, 500, ccbsnr_tell_activated,
|
||||
(void *)(unsigned long)handle) != 0) {
|
||||
/* we got a hangup */
|
||||
cc_verbose(3, 1,
|
||||
VERBOSE_PREFIX_3 CC_MESSAGE_NAME " ccbs: hangup.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (get_ccbsnr_link(0, 0, handle, 0xffff, &ccbsnrstate, NULL) != NULL) {
|
||||
if (ccbsnrstate == CCBSNR_ACTIVATED) {
|
||||
result = goodresult;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cc_verbose(3, 1, VERBOSE_PREFIX_3, CC_MESSAGE_NAME
|
||||
" ccbs: linkid %d not found in table.\n", linkid);
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(c, "CCBSSTATUS", result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _PBX_CAPI_SUPP_H
|
||||
#define _PBX_CAPI_SUPP_H
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern void ListenOnSupplementary(unsigned controller);
|
||||
extern int handle_facility_indication_supplementary(
|
||||
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
|
||||
extern void handle_facility_confirmation_supplementary(
|
||||
_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt **i,
|
||||
struct ast_channel** interface_owner);
|
||||
extern int pbx_capi_ccbs(struct ast_channel *c, char *data);
|
||||
extern int pbx_capi_ccbsstop(struct ast_channel *c, char *data);
|
||||
extern int pbx_capi_ccpartybusy(struct ast_channel *c, char *data);
|
||||
extern void cleanup_ccbsnr(void);
|
||||
extern unsigned int capi_get_ccbsnrcontroller(unsigned int handle);
|
||||
extern _cword capi_ccbsnr_take_ref(unsigned int handle);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* An implementation of Common ISDN API 2.0 for Asterisk
|
||||
*
|
||||
* Copyright (C) 2006-2009 Cytronics & Melware
|
||||
*
|
||||
* Armin Schindler <armin@melware.de>
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*/
|
||||
|
||||
#ifndef _PBX_CAPI_UTILS_H
|
||||
#define _PBX_CAPI_UTILS_H
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
extern int capidebug;
|
||||
extern char *emptyid;
|
||||
|
||||
extern void cc_verbose_internal(char *text, ...);
|
||||
|
||||
static inline int cc_verbose_check(int o_v, int c_d)
|
||||
{
|
||||
if (unlikely(((o_v == 0) || (option_verbose > o_v)) &&
|
||||
((!c_d) || ((c_d) && (capidebug))))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper for <pbx>_verbose with different verbose settings
|
||||
*/
|
||||
#define cc_verbose(o_v,c_d,text, args...) do { \
|
||||
if (cc_verbose_check(o_v, c_d) != 0) { \
|
||||
cc_verbose_internal(text , ## args); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
extern _cword get_capi_MessageNumber(void);
|
||||
extern struct capi_pvt *capi_find_interface_by_msgnum(unsigned short msgnum);
|
||||
extern struct capi_pvt *capi_find_interface_by_plci(unsigned int plci);
|
||||
extern MESSAGE_EXCHANGE_ERROR capi_wait_conf(struct capi_pvt *i, unsigned short wCmd);
|
||||
extern MESSAGE_EXCHANGE_ERROR capidev_check_wait_get_cmsg(_cmsg *CMSG);
|
||||
extern char *capi_info_string(unsigned int info);
|
||||
extern void show_capi_info(struct capi_pvt *i, _cword info);
|
||||
extern unsigned capi_ListenOnController(unsigned int CIPmask, unsigned controller);
|
||||
extern unsigned capi_ManufacturerAllowOnController(unsigned controller);
|
||||
extern void capi_parse_dialstring(char *buffer, char **interface, char **dest, char **param, char **ocid);
|
||||
extern char *capi_number_func(unsigned char *data, unsigned int strip, char *buf);
|
||||
extern int cc_add_peer_link_id(struct ast_channel *c);
|
||||
extern struct ast_channel *cc_get_peer_link_id(const char *p);
|
||||
extern void capi_remove_nullif(struct capi_pvt *i);
|
||||
extern struct capi_pvt *capi_mknullif(struct ast_channel *c, unsigned long long controllermask);
|
||||
struct capi_pvt *capi_mkresourceif(struct ast_channel *c, unsigned long long controllermask, struct capi_pvt *data_plci_ifc, cc_format_t codecs, int all);
|
||||
extern int capi_create_reader_writer_pipe(struct capi_pvt *i);
|
||||
extern struct ast_frame *capi_read_pipeframe(struct capi_pvt *i);
|
||||
extern int capi_write_frame(struct capi_pvt *i, struct ast_frame *f);
|
||||
extern int capi_verify_resource_plci(const struct capi_pvt *i);
|
||||
extern const char* pbx_capi_get_cid (struct ast_channel* c, const char *notAvailableVisual);
|
||||
extern const char* pbx_capi_get_callername (struct ast_channel* c, const char *notAvailableVisual);
|
||||
const char* pbx_capi_get_connectedname (struct ast_channel* c, const char *notAvailableVisual);
|
||||
char* pbx_capi_strsep_controller_list (char** param);
|
||||
|
||||
#define capi_number(data, strip) \
|
||||
capi_number_func(data, strip, alloca(AST_MAX_EXTENSION))
|
||||
|
||||
typedef struct capi_prestruct_s {
|
||||
unsigned short wLen;
|
||||
unsigned char *info;
|
||||
} capi_prestruct_t;
|
||||
|
||||
/*
|
||||
* Eicon's capi_sendf() function to create capi messages easily
|
||||
* and send this message.
|
||||
* Copyright by Eicon Networks / Dialogic
|
||||
*/
|
||||
extern MESSAGE_EXCHANGE_ERROR capi_sendf(
|
||||
struct capi_pvt *capii, int waitconf,
|
||||
_cword command, _cdword Id, _cword Number, char * format, ...);
|
||||
|
||||
/*!
|
||||
\brief nulliflist
|
||||
*/
|
||||
const struct capi_pvt *pbx_capi_get_nulliflist(void);
|
||||
/*!
|
||||
\brief cc_mutex_lock(&nullif_lock)
|
||||
*/
|
||||
void pbx_capi_nulliflist_lock(void);
|
||||
/*!
|
||||
\brief cc_mutex_unlock(&nullif_lock)
|
||||
*/
|
||||
void pbx_capi_nulliflist_unlock(void);
|
||||
|
||||
#endif
|
398
create_config.sh
398
create_config.sh
|
@ -5,26 +5,61 @@
|
|||
# Script to create config.h for compatibility with
|
||||
# different asterisk versions.
|
||||
#
|
||||
# (C) 2005 Cytronics & Melware
|
||||
# (C) 2005-2007 Cytronics & Melware
|
||||
# Armin Schindler <armin@melware.de>
|
||||
#
|
||||
|
||||
CONFIGFILE="config.h"
|
||||
rm -f "$CONFIGFILE"
|
||||
|
||||
VER=1_2
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo >&2 "Missing argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
INCLUDEDIR="$1/asterisk"
|
||||
AST_BINARY="$1/../sbin/asterisk"
|
||||
|
||||
if [ ! -d "$INCLUDEDIR" ]; then
|
||||
echo >&2 "Include directory '$INCLUDEDIR' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking Asterisk version..."
|
||||
echo -n "Checking Asterisk version... "
|
||||
AVERSIONNUM=`sed -n '/.*ASTERISK_VERSION_NUM /s/^.*ASTERISK_VERSION_NUM //p' $INCLUDEDIR/version.h`
|
||||
AVERSION=`sed -n '/.*ASTERISK_VERSION /s/^.*ASTERISK_VERSION //p' $INCLUDEDIR/version.h`
|
||||
AVERSION=`echo $AVERSION | sed 's/\"//g'`
|
||||
if [ "$AVERSION" = "" ]; then
|
||||
# Asterisk 11 and up removed version information in its version.h header file.
|
||||
# ast_get_version() and ast_get_version_num() are not usable by external
|
||||
# modules like chan_capi, as there's no library implementing these functions,
|
||||
# so linking will always fail.
|
||||
# Workaround that by trying to run asterisk -V and parse the output.
|
||||
LD_LIBRARY_PATH=$INSTALL_PREFIX/usr/lib:$LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH
|
||||
AVERSION=$("$AST_BINARY" -V)
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
AVERSION="$(echo "$AVERSION" | sed -e 's/Asterisk //g')"
|
||||
AVERSIONNUM="$(echo "$AVERSION" |sed -e 's/\.//g')"
|
||||
echo $AVERSIONNUM | grep -q GIT >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
AVERSIONNUM=$(echo $AVERSIONNUM | awk -F '-' '{print $2}')
|
||||
fi
|
||||
# Set VER later automatically based on $AVERSIONNUM.
|
||||
else
|
||||
AVERSION="trunk"
|
||||
VER="1_6"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$AVERSIONNUM" ]; then
|
||||
AVERSIONNUM=999999
|
||||
AVERSION="trunk"
|
||||
VER="1_6"
|
||||
fi
|
||||
echo $AVERSION
|
||||
|
||||
echo "/*" >$CONFIGFILE
|
||||
echo " * automatically generated by $0 `date`" >>$CONFIGFILE
|
||||
|
@ -34,98 +69,297 @@ echo "#ifndef CHAN_CAPI_CONFIG_H" >>$CONFIGFILE
|
|||
echo "#define CHAN_CAPI_CONFIG_H" >>$CONFIGFILE
|
||||
echo >>$CONFIGFILE
|
||||
|
||||
if grep -q "struct ast_channel_tech" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAVE_TECH_PVT" >>$CONFIGFILE
|
||||
echo " * found 'struct ast_channel_tech'"
|
||||
else
|
||||
echo "#undef CC_AST_HAVE_TECH_PVT" >>$CONFIGFILE
|
||||
echo " * no 'struct ast_channel_tech', using old pvt"
|
||||
fi
|
||||
case "$AVERSIONNUM" in
|
||||
14*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_10_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_11_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_13_0" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 14"
|
||||
VER=14_0
|
||||
;;
|
||||
13*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_10_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_11_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_13_0" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 13"
|
||||
VER=13_0
|
||||
;;
|
||||
11*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_10_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_11_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 11"
|
||||
VER=11_0
|
||||
;;
|
||||
100*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_10_0" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 10"
|
||||
VER=10_0
|
||||
;;
|
||||
108*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_VERSION_1_8" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 1.8"
|
||||
VER=1_8
|
||||
;;
|
||||
106*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EVENT_MWI" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 1.6"
|
||||
VER=1_6
|
||||
;;
|
||||
104*)
|
||||
echo "#define CC_AST_HAS_VERSION_1_4" >>$CONFIGFILE
|
||||
echo " * found Asterisk version 1.4"
|
||||
VER=1_4
|
||||
;;
|
||||
99999)
|
||||
echo "#define CC_AST_HAS_VERSION_1_4" >>$CONFIGFILE
|
||||
echo " * assuming Asterisk version 1.4"
|
||||
VER=1_4
|
||||
;;
|
||||
999999)
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo " * assuming Asterisk version 1.6"
|
||||
VER=1_6
|
||||
;;
|
||||
*)
|
||||
if [ "$VER" = "1_6" ]; then
|
||||
echo "#define CC_AST_HAS_VERSION_1_6" >>$CONFIGFILE
|
||||
echo " * assuming Asterisk version 1.6"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_VERSION_1_4" >>$CONFIGFILE
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if grep -q "ast_bridged_channel" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_BRIDGED_CHANNEL" >>$CONFIGFILE
|
||||
echo " * found 'ast_bridged_channel'"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_BRIDGED_CHANNEL" >>$CONFIGFILE
|
||||
echo " * no 'ast_bridged_channel'"
|
||||
fi
|
||||
check_two_and_four()
|
||||
{
|
||||
if grep -q "AST_STRING_FIELD(name)" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_STRINGFIELD_IN_CHANNEL" >>$CONFIGFILE
|
||||
echo " * found stringfield in ast_channel"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_STRINGFIELD_IN_CHANNEL" >>$CONFIGFILE
|
||||
echo " * no stringfield in ast_channel"
|
||||
fi
|
||||
|
||||
if grep -q "const indicate.*datalen" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_INDICATE_DATA" >>$CONFIGFILE
|
||||
echo " * found 'indicate' with data"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_INDICATE_DATA" >>$CONFIGFILE
|
||||
echo " * no data on 'indicate'"
|
||||
fi
|
||||
|
||||
if grep -q "ast_channel_alloc.*name_fmt" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_EXT_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * found extended ast_channel_alloc"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_EXT_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * no extended ast_channel_alloc"
|
||||
fi
|
||||
|
||||
if grep -q "ast_bridge_result" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_BRIDGE_RESULT" >>$CONFIGFILE
|
||||
echo " * found 'ast_bridge_result'"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_BRIDGE_RESULT" >>$CONFIGFILE
|
||||
echo " * no 'ast_bridge_result'"
|
||||
fi
|
||||
if grep -q "ast_channel_alloc.*amaflag" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_EXT2_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * found second extended ast_channel_alloc"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_EXT2_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * no second extended ast_channel_alloc"
|
||||
fi
|
||||
|
||||
if grep -q "struct ast_channel \*\*rc, int timeoutms" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_BRIDGE_WITH_TIMEOUTMS" >>$CONFIGFILE
|
||||
echo " * found bridge with timeoutms"
|
||||
else
|
||||
echo "#undef CC_AST_BRIDGE_WITH_TIMEOUTMS" >>$CONFIGFILE
|
||||
echo " * no timeoutms in bridge"
|
||||
fi
|
||||
if grep -q "send_digit_end.*duration" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_SEND_DIGIT_END_DURATION" >>$CONFIGFILE
|
||||
echo " * found send_digit_end with duration"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_SEND_DIGIT_END_DURATION" >>$CONFIGFILE
|
||||
echo " * no duration with send_digit_end"
|
||||
fi
|
||||
|
||||
if grep -q "ast_dsp_process*needlock" $INCLUDEDIR/dsp.h; then
|
||||
echo "#define CC_AST_DSP_PROCESS_NEEDLOCK" >>$CONFIGFILE
|
||||
echo " * ast_dsp_process() needs 'needlock'"
|
||||
else
|
||||
echo "#undef CC_AST_DSP_PROCESS_NEEDLOCK" >>$CONFIGFILE
|
||||
echo " * ast_dsp_process() without 'needlock'"
|
||||
fi
|
||||
if [ "$VER" = "1_2" ]; then
|
||||
if grep -q "AST_JB" $INCLUDEDIR/channel.h; then
|
||||
if [ ! -f "$INCLUDEDIR/../../lib/asterisk/modules/chan_sip.so" ]; then
|
||||
echo "/* AST_JB */" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_JB_PATCH" >>$CONFIGFILE
|
||||
echo " * assuming generic jitter-buffer patch"
|
||||
else
|
||||
if grep -q "ast_jb" "$INCLUDEDIR/../../lib/asterisk/modules/chan_sip.so"; then
|
||||
echo "/* AST_JB */" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_JB_PATCH" >>$CONFIGFILE
|
||||
echo " * found generic jitter-buffer patch"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_JB_PATCH" >>$CONFIGFILE
|
||||
echo " * found DISABLED generic jitter-buffer patch"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "#undef CC_AST_HAS_JB_PATCH" >>$CONFIGFILE
|
||||
echo " * without generic jitter-buffer patch"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if grep -q "struct ast_callerid" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_CHANNEL_HAS_CID" >>$CONFIGFILE
|
||||
echo " * found 'struct ast_callerid'"
|
||||
else
|
||||
echo "#undef CC_AST_CHANNEL_HAS_CID" >>$CONFIGFILE
|
||||
echo " * no 'struct ast_callerid'"
|
||||
fi
|
||||
check_version_onesix()
|
||||
{
|
||||
echo "#define CC_AST_HAS_VERSION_1_4" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_STRINGFIELD_IN_CHANNEL" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_INDICATE_DATA" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EXT_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_EXT2_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo "#define CC_AST_HAS_SEND_DIGIT_END_DURATION" >>$CONFIGFILE
|
||||
|
||||
if grep -q "struct timeval delivery" $INCLUDEDIR/frame.h; then
|
||||
echo "#define CC_AST_FRAME_HAS_TIMEVAL" >>$CONFIGFILE
|
||||
echo " * found 'struct timeval delivery'"
|
||||
else
|
||||
echo "#undef CC_AST_FRAME_HAS_TIMEVAL" >>$CONFIGFILE
|
||||
echo " * no 'struct timeval delivery'"
|
||||
fi
|
||||
if grep -q "int ast_dsp_set_digitmode" $INCLUDEDIR/dsp.h; then
|
||||
echo "#define CC_AST_HAS_DSP_SET_DIGITMODE" >>$CONFIGFILE
|
||||
echo " * found new 'ast_dsp_set_digitmode' function"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_DSP_SET_DIGITMODE" >>$CONFIGFILE
|
||||
echo " * no new 'ast_dsp_set_digitmode' function"
|
||||
fi
|
||||
if grep -q "union .* data" $INCLUDEDIR/frame.h; then
|
||||
echo "#define CC_AST_HAS_UNION_DATA_IN_FRAME" >>$CONFIGFILE
|
||||
echo " * found new union data in ast_frame structure"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_UNION_DATA_IN_FRAME" >>$CONFIGFILE
|
||||
echo " * no new union data in ast_frame structure"
|
||||
fi
|
||||
if grep -q "union ast_frame_subclass subclass" $INCLUDEDIR/frame.h; then
|
||||
echo "#define CC_AST_HAS_UNION_SUBCLASS_IN_FRAME" >>$CONFIGFILE
|
||||
echo " * found new union subclass in ast_frame structure"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_UNION_SUBCLASS_IN_FRAME" >>$CONFIGFILE
|
||||
echo " * no new union subclass in ast_frame structure"
|
||||
fi
|
||||
if grep -q "ast_channel_release.*struct" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE
|
||||
echo " * found ast_channel_release function"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_CHANNEL_RELEASE" >>$CONFIGFILE
|
||||
echo " * no new ast_channel_release function"
|
||||
fi
|
||||
if grep -q "ast_devstate2str.*enum" $INCLUDEDIR/devicestate.h; then
|
||||
echo "#define CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE
|
||||
echo " * found new ast_devstate2str function"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_AST_DEVSTATE2STR" >>$CONFIGFILE
|
||||
echo " * obsolete devstate2str function"
|
||||
fi
|
||||
if grep -q "ast_devstate_changed.*ast_devstate_cache" $INCLUDEDIR/devicestate.h; then
|
||||
echo "#define CC_AST_HAS_AST_DEVSTATE_CACHE" >>$CONFIGFILE
|
||||
echo " * found ast_devstate_cache in ast_devstate_changed function"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_AST_DEVSTATE_CACHE" >>$CONFIGFILE
|
||||
echo " * no ast_devstate_cache in ast_devstate_changed function"
|
||||
fi
|
||||
if grep -q "ast_request.*requestor" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE
|
||||
echo " * found requestor in ast_request"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_REQUEST_REQUESTOR" >>$CONFIGFILE
|
||||
echo " * no requestor in ast_request"
|
||||
fi
|
||||
if grep -q "ast_request.*format_t format" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_REQUEST_FORMAT_T" >>$CONFIGFILE
|
||||
echo " * found format_t in ast_request"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_REQUEST_FORMAT_T" >>$CONFIGFILE
|
||||
echo " * no format_t in ast_request"
|
||||
fi
|
||||
if grep -q "ast_register_application2.*void " $INCLUDEDIR/module.h; then
|
||||
echo "#undef CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE
|
||||
echo " * no const char in ast_register_application"
|
||||
else
|
||||
echo "#define CC_AST_HAS_CONST_CHAR_IN_REGAPPL" >>$CONFIGFILE
|
||||
echo " * found const char in ast_register_application"
|
||||
fi
|
||||
if grep -q "ast_channel_alloc.*linkedid" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * found linkedid in ast_channel_alloc"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_LINKEDID_CHAN_ALLOC" >>$CONFIGFILE
|
||||
echo " * no linkedid in ast_channel_alloc"
|
||||
fi
|
||||
if [ -f $INCLUDEDIR/frame_defs.h ]; then
|
||||
if grep -q "typedef.*format_t" $INCLUDEDIR/frame_defs.h; then
|
||||
echo "#define CC_AST_HAS_FORMAT_T" >>$CONFIGFILE
|
||||
echo " * found format_t in frame_defs"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_FORMAT_T" >>$CONFIGFILE
|
||||
echo " * no format_t in frame_defs"
|
||||
fi
|
||||
else
|
||||
echo "#undef CC_AST_HAS_FORMAT_T" >>$CONFIGFILE
|
||||
fi
|
||||
if [ -f $INCLUDEDIR/rtp_engine.h ]; then
|
||||
echo "#define CC_AST_HAS_RTP_ENGINE_H" >>$CONFIGFILE
|
||||
echo " * found rtp_engine.h"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_RTP_ENGINE_H" >>$CONFIGFILE
|
||||
echo " * no rtp_engine.h"
|
||||
fi
|
||||
if [ -f $INCLUDEDIR/netsock2.h ]; then
|
||||
if grep -q "struct ast_sockaddr " $INCLUDEDIR/netsock2.h; then
|
||||
echo "#define CC_AST_HAS_AST_SOCKADDR" >>$CONFIGFILE
|
||||
echo " * found ast_sockaddr structure"
|
||||
else
|
||||
echo "#undef CC_AST_HAS_AST_SOCKADDR" >>$CONFIGFILE
|
||||
echo " * no ast_sockaddr structure"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if grep -q "transfercapability" $INCLUDEDIR/channel.h; then
|
||||
echo "#define CC_AST_CHANNEL_HAS_TRANSFERCAP" >>$CONFIGFILE
|
||||
echo " * found 'transfercapability'"
|
||||
else
|
||||
echo "#undef CC_AST_CHANNEL_HAS_TRANSFERCAP" >>$CONFIGFILE
|
||||
echo " * no 'transfercapability'"
|
||||
fi
|
||||
|
||||
if grep -q "ast_config_load" $INCLUDEDIR/config.h; then
|
||||
echo " * found 'ast_config_load'"
|
||||
else
|
||||
echo "#define ast_config_load(x) ast_load(x)" >>$CONFIGFILE
|
||||
echo "#define ast_config_destroy(x) ast_destroy(x)" >>$CONFIGFILE
|
||||
echo " * no 'ast_config_load'"
|
||||
fi
|
||||
|
||||
if grep -q "AST_CONTROL_HOLD" $INCLUDEDIR/frame.h; then
|
||||
echo "#define CC_AST_CONTROL_HOLD" >>$CONFIGFILE
|
||||
echo " * found 'AST_CONTROL_HOLD'"
|
||||
else
|
||||
echo "#undef CC_AST_CONTROL_HOLD" >>$CONFIGFILE
|
||||
echo " * no 'AST_CONTROL_HOLD'"
|
||||
fi
|
||||
|
||||
if grep -q "struct ast_custom_function " $INCLUDEDIR/pbx.h; then
|
||||
echo "#define CC_AST_CUSTOM_FUNCTION" >>$CONFIGFILE
|
||||
echo " * found 'struct ast_custom_function'"
|
||||
else
|
||||
echo "#undef CC_AST_CUSTOM_FUNCTION" >>$CONFIGFILE
|
||||
echo " * no 'struct ast_custom_function'"
|
||||
fi
|
||||
case $VER in
|
||||
1_2)
|
||||
echo "Using Asterisk 1.2 API"
|
||||
check_two_and_four
|
||||
;;
|
||||
1_4)
|
||||
echo "Using Asterisk 1.4 API"
|
||||
check_two_and_four
|
||||
;;
|
||||
1_6)
|
||||
echo "Using Asterisk 1.6 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
1_8)
|
||||
echo "Using Asterisk 1.8 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
10_0)
|
||||
echo "Using Asterisk 10.0 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
11_0)
|
||||
echo "Using Asterisk 11.0 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
13_0)
|
||||
echo "Using Asterisk 13.0 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
14_0)
|
||||
echo "Using Asterisk 14.0 API"
|
||||
check_version_onesix
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Asterisk version invalid."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "" >>$CONFIGFILE
|
||||
echo "#endif /* CHAN_CAPI_CONFIG_H */" >>$CONFIGFILE
|
||||
echo "" >>$CONFIGFILE
|
||||
|
||||
echo "config.h complete."
|
||||
echo
|
||||
exit 0
|
||||
|
||||
|
|
|
@ -0,0 +1,753 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Implements to access Diva management file system
|
||||
*
|
||||
* \par Access to Diva hardware state
|
||||
* divalogd captures information from Diva management and exports
|
||||
* it CVS file format.
|
||||
*
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "divastreaming/platform.h"
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "dlist.h"
|
||||
#include "divastatus_parameters.h"
|
||||
#include "divastatus_ifc.h"
|
||||
#include "divastatus.h"
|
||||
#ifdef CC_USE_INOTIFY
|
||||
#include <fcntl.h>
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
|
||||
typedef const char* pcchar;
|
||||
|
||||
static pcchar DIVA_STATUS_PATH = "/usr/lib/eicon/divas/registry/ifc";
|
||||
static pcchar DIVA_STATUS_FILE = "ifcstate";
|
||||
static pcchar DIVA_INFO_FILE = "info";
|
||||
static pcchar DIVA_CONFIG_FILE = "info/Config";
|
||||
static pcchar DIVA_SERIAL_FILE = "serial";
|
||||
static pcchar DIVA_READ_ALARM_FILE = "info/Red Alarm";
|
||||
static pcchar DIVA_YELLOW_ALARM_FILE = "info/Yellow Alarm";
|
||||
static pcchar DIVA_BLUE_ALARM_FILE = "info/Blue Alarm";
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
struct _diva_status_ifc;
|
||||
static int diva_status_active(void);
|
||||
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state);
|
||||
static char* diva_status_read_file(unsigned int controller, const char* fileName);
|
||||
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir);
|
||||
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state (const diva_status_ifc_state_t* state);
|
||||
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state (const diva_status_ifc_state_t* state);
|
||||
static int diva_status_map_CAPI2XDI(int capiController);
|
||||
static void diva_status_process_event(struct _diva_status_ifc *controllerState, int initialStateIndex, int newStateIndex);
|
||||
#ifdef CC_USE_INOTIFY
|
||||
static pcchar DIVA_DIVA_FS_PATH = "/usr/lib/eicon/divas/registry/ifc";
|
||||
static void diva_status_cleanup_wd(int wd);
|
||||
static int divaFsWd = -1; /*! \brief Diva fs state */
|
||||
#endif
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static
|
||||
#endif
|
||||
char diva_status_ifc_state_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " ifcstate\n"
|
||||
" Show info about interfaces.\n";
|
||||
|
||||
|
||||
static int inotifyFd = -1; /*! \brief inotify descriptor */
|
||||
static diva_entity_queue_t controller_q; /*! \brief Active controllers. \note List changed only while CAPI thread is not running */
|
||||
|
||||
typedef struct _diva_status_ifc {
|
||||
diva_entity_link_t link;
|
||||
int capiController;
|
||||
int idiController;
|
||||
diva_status_ifc_state_t state[2];
|
||||
int currentState;
|
||||
int ifstateWd;
|
||||
int infoWd;
|
||||
diva_status_changed_cb_proc_t status_changed_notify_proc; /*! \brief Notify about interface state change */
|
||||
diva_hwstatus_changed_cb_proc_t hw_status_changed_notify_proc; /*! \brief Notify about hardware state change */
|
||||
time_t changeTime; /*! \brief Time interface state changed */
|
||||
time_t unavailableChangeTime; /*! \brief Time interface state changed to unavailable */
|
||||
time_t hwChangeTime; /*! \brief Time hardware state changed */
|
||||
time_t unavailableHwChangeTime; /*! \brief Time hardware state changed to unavailable */
|
||||
} diva_status_ifc_t;
|
||||
|
||||
diva_status_interface_state_t diva_status_init_interface(int controller,
|
||||
diva_status_hardware_state_t* hwState,
|
||||
diva_status_changed_cb_proc_t fn,
|
||||
diva_hwstatus_changed_cb_proc_t hwfn)
|
||||
{
|
||||
int idiController = diva_status_map_CAPI2XDI(controller);
|
||||
diva_status_ifc_t* controllerState = idiController > 0 ? (ast_malloc(sizeof(*controllerState))) : 0;
|
||||
diva_status_interface_state_t ret = DivaStatusInterfaceStateNotAvailable;
|
||||
|
||||
if (controllerState != 0) {
|
||||
controllerState->capiController = controller;
|
||||
controllerState->idiController = idiController;
|
||||
controllerState->status_changed_notify_proc = fn;
|
||||
controllerState->hw_status_changed_notify_proc = hwfn;
|
||||
controllerState->ifstateWd = -1;
|
||||
controllerState->infoWd = -1;
|
||||
diva_status_create_wd(&controllerState->ifstateWd, idiController, DIVA_STATUS_FILE, 0);
|
||||
diva_status_create_wd(&controllerState->infoWd, idiController, DIVA_INFO_FILE, 1);
|
||||
controllerState->currentState = 0;
|
||||
controllerState->changeTime = time(NULL);
|
||||
diva_status_get_controller_state(idiController, &controllerState->state[controllerState->currentState]);
|
||||
diva_q_add_tail(&controller_q, &controllerState->link);
|
||||
ret = diva_status_get_interface_state_from_idi_state(&controllerState->state[controllerState->currentState]);
|
||||
*hwState = diva_status_get_hw_state_from_idi_state(&controllerState->state[controllerState->currentState]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void diva_status_cleanup_interface (int controller)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
||||
|
||||
if (controllerState->capiController == controller) {
|
||||
diva_q_remove(&controller_q, link);
|
||||
#ifdef CC_USE_INOTIFY
|
||||
if (controllerState->ifstateWd >= 0)
|
||||
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
|
||||
if (controllerState->infoWd >= 0)
|
||||
inotify_rm_watch(inotifyFd, controllerState->infoWd);
|
||||
#endif
|
||||
ast_free (controllerState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CC_USE_INOTIFY
|
||||
if (diva_q_get_head(&controller_q) == 0) {
|
||||
if (divaFsWd >= 0) {
|
||||
inotify_rm_watch(inotifyFd, divaFsWd);
|
||||
divaFsWd = -1;
|
||||
}
|
||||
if (inotifyFd >= 0) {
|
||||
close(inotifyFd);
|
||||
inotifyFd = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int diva_status_get_waitable_object(void)
|
||||
{
|
||||
return inotifyFd;
|
||||
}
|
||||
|
||||
void diva_status_process_events(void)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
/*
|
||||
Polling
|
||||
*/
|
||||
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
||||
if ((controllerState->ifstateWd < 0) || (controllerState->infoWd < 0)) {
|
||||
int currentState = controllerState->currentState;
|
||||
diva_status_create_wd(&controllerState->ifstateWd, controllerState->idiController, DIVA_STATUS_FILE, 0);
|
||||
diva_status_create_wd(&controllerState->infoWd, controllerState->idiController, DIVA_INFO_FILE, 1);
|
||||
controllerState->currentState = (controllerState->currentState + 1) % 2;
|
||||
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
|
||||
diva_status_process_event(controllerState, currentState, controllerState->currentState);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Events
|
||||
*/
|
||||
#ifdef CC_USE_INOTIFY
|
||||
if (inotifyFd >= 0 && divaFsWd >= 0) {
|
||||
unsigned char buffer[1024];
|
||||
int length;
|
||||
int i;
|
||||
|
||||
while ((length = read(inotifyFd, buffer, sizeof(buffer))) > 0) {
|
||||
i = 0;
|
||||
while (i < length) {
|
||||
struct inotify_event *event = (struct inotify_event*)&buffer[i];
|
||||
|
||||
if ((event->mask & (IN_IGNORED|IN_DELETE_SELF|IN_UNMOUNT|IN_Q_OVERFLOW)) != 0) {
|
||||
diva_status_cleanup_wd((event->mask & IN_IGNORED) == 0 ? event->wd : -1);
|
||||
break;
|
||||
}
|
||||
if (event->wd != divaFsWd) {
|
||||
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
||||
if ((controllerState->ifstateWd == event->wd) || (controllerState->infoWd == event->wd)) {
|
||||
int currentState = controllerState->currentState;
|
||||
controllerState->currentState = (controllerState->currentState + 1) % 2;
|
||||
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
|
||||
diva_status_process_event(controllerState, currentState, controllerState->currentState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += sizeof(*event) + event->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CC_USE_INOTIFY
|
||||
static void diva_status_cleanup_wd(int wd)
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
||||
|
||||
if ((controllerState->ifstateWd >= 0) && (wd != controllerState->ifstateWd)) {
|
||||
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
|
||||
}
|
||||
controllerState->ifstateWd = -1;
|
||||
if ((controllerState->infoWd >= 0) && (wd != controllerState->infoWd)) {
|
||||
inotify_rm_watch(inotifyFd, controllerState->infoWd);
|
||||
}
|
||||
controllerState->infoWd = -1;
|
||||
}
|
||||
|
||||
if ((divaFsWd >= 0) && (wd != divaFsWd)) {
|
||||
inotify_rm_watch(inotifyFd, divaFsWd);
|
||||
}
|
||||
divaFsWd = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void diva_status_process_event(diva_status_ifc_t *controllerState, int initialStateIndex, int newStateIndex)
|
||||
{
|
||||
diva_status_ifc_state_t* initialState = &controllerState->state[initialStateIndex];
|
||||
diva_status_ifc_state_t* newState = &controllerState->state[newStateIndex];
|
||||
diva_status_interface_state_t initialIfcState = diva_status_get_interface_state_from_idi_state (initialState);
|
||||
diva_status_interface_state_t newIfcState = diva_status_get_interface_state_from_idi_state (newState);
|
||||
diva_status_hardware_state_t initalHwState = diva_status_get_hw_state_from_idi_state(initialState);
|
||||
diva_status_hardware_state_t newHwState = diva_status_get_hw_state_from_idi_state(newState);
|
||||
time_t t = time(NULL);
|
||||
|
||||
if (initialIfcState != newIfcState) {
|
||||
controllerState->changeTime = t;
|
||||
|
||||
if (newIfcState == DivaStatusInterfaceStateERROR)
|
||||
controllerState->unavailableChangeTime = t;
|
||||
|
||||
controllerState->status_changed_notify_proc(controllerState->capiController, newIfcState);
|
||||
}
|
||||
|
||||
if (initalHwState != newHwState) {
|
||||
controllerState->hwChangeTime = t;
|
||||
|
||||
if (newHwState == DivaStatusHardwareStateERROR)
|
||||
controllerState->unavailableHwChangeTime = t;
|
||||
|
||||
controllerState->hw_status_changed_notify_proc(controllerState->capiController, newHwState);
|
||||
}
|
||||
}
|
||||
|
||||
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir)
|
||||
{
|
||||
#ifdef CC_USE_INOTIFY
|
||||
if (inotifyFd < 0) {
|
||||
inotifyFd = inotify_init();
|
||||
if (inotifyFd >= 0)
|
||||
fcntl(inotifyFd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
if (inotifyFd >= 0 && divaFsWd < 0) {
|
||||
divaFsWd = inotify_add_watch (inotifyFd, DIVA_DIVA_FS_PATH, IN_DELETE_SELF | IN_UNMOUNT | IN_IGNORED);
|
||||
}
|
||||
|
||||
if (*wd >= 0)
|
||||
return;
|
||||
|
||||
if (inotifyFd >= 0 && divaFsWd >= 0) {
|
||||
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
|
||||
char name[name_len];
|
||||
|
||||
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
|
||||
name[name_len-1] = 0;
|
||||
|
||||
*wd = inotify_add_watch (inotifyFd, name,
|
||||
IN_CLOSE_WRITE | IN_DELETE_SELF | IN_IGNORED | ((isDir != 0) ? IN_DELETE : 0));
|
||||
|
||||
return;
|
||||
}
|
||||
#else
|
||||
*wd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Check divalogd is available
|
||||
*/
|
||||
static int diva_status_active(void)
|
||||
{
|
||||
struct stat v;
|
||||
|
||||
return ((stat(DIVA_STATUS_PATH, &v) == 0 && S_ISDIR(v.st_mode) != 0) ? 0 : -1);
|
||||
}
|
||||
|
||||
static char* diva_status_read_file(unsigned int controller, const char* fileName)
|
||||
{
|
||||
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
|
||||
char name[name_len];
|
||||
struct stat v;
|
||||
int fd;
|
||||
int length;
|
||||
char *data, *p;
|
||||
|
||||
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
|
||||
name[name_len-1] = 0;
|
||||
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
if (fstat(fd, &v) != 0 || v.st_size == 0) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = MIN(v.st_size, 16U*1024U);
|
||||
|
||||
data = ast_malloc(length+1);
|
||||
if (data == 0) {
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read(fd, data, length) != length) {
|
||||
ast_free(data);
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
data[length] = 0;
|
||||
|
||||
while (((p = strchr(data, '\n')) != 0) || ((p = strchr(data, '\r')))) {
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state)
|
||||
{
|
||||
char *data, *p;
|
||||
int i, pri, bri;
|
||||
const char* v;
|
||||
|
||||
memset (state, 0x00, sizeof(*state));
|
||||
state->ifcType = DivaStatusIfcNotPri;
|
||||
state->hwState = DivaStatusHwStateUnknown;
|
||||
state->ifcL1State = DivaStatusIfcL2DoNotApply;
|
||||
state->ifcL2State = DivaStatusIfcL2DoNotApply;
|
||||
state->ifcL1VisualState = DivaStatusIfcL2DoNotApply;
|
||||
state->ifcL2VisualState = DivaStatusIfcL2DoNotApply;
|
||||
|
||||
if (diva_status_active() != 0)
|
||||
return -1;
|
||||
|
||||
if ((data = diva_status_read_file(controller, DIVA_CONFIG_FILE)) == 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0, pri = 0, bri = 0, p = data, v = strsep(&p, ",");
|
||||
v != 0 && i < DivaStateIfcConfig_Max;
|
||||
v = strsep(&p, ","), i++) {
|
||||
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
|
||||
const char *tmp;
|
||||
do {
|
||||
if ((p != 0) && (*p != 0))
|
||||
p[-1] = ',';
|
||||
tmp = strsep (&p, ",");
|
||||
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
|
||||
}
|
||||
|
||||
switch ((diva_state_ifc_config_parameters_t)i) {
|
||||
case DivaStateIfcConfig_TYPE:
|
||||
pri += (strcmp ("PRI", v) == 0);
|
||||
bri += (strcmp ("BRI", v) == 0);
|
||||
break;
|
||||
|
||||
case DivaStateIfcConfig_PRI:
|
||||
pri += (strcmp ("'YES'", v) == 0);
|
||||
bri += (strcmp ("'NO'", v) == 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_free(data);
|
||||
|
||||
state->ifcType = (pri == 2) ? DivaStatusIfcPri : DivaStatusIfcNotPri;
|
||||
if (bri == 2) {
|
||||
state->ifcType = DivaStatusIfcBri;
|
||||
}
|
||||
|
||||
if ((data = diva_status_read_file(controller, DIVA_STATUS_FILE)) == 0)
|
||||
return (-1);
|
||||
|
||||
for (i = 0, p = data, v = strsep (&p, ","); v != 0 && i < (int)DivaStateIfcState_Max; v = strsep (&p, ","), i++) {
|
||||
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
|
||||
const char *tmp;
|
||||
do {
|
||||
if ((p != 0) && (*p != 0))
|
||||
p[-1] = ',';
|
||||
tmp = strsep (&p, ",");
|
||||
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
|
||||
}
|
||||
|
||||
switch ((diva_state_ifcstate_parameters_t)i) {
|
||||
case DivaStateIfcState_LAYER1_STATE:
|
||||
state->ifcL1VisualState = (strcmp ("'Activated'", v) == 0) ? DivaStatusIfcL1OK : DivaStatusIfcL1Error;
|
||||
if (state->ifcType == DivaStatusIfcPri) {
|
||||
state->ifcL1State = state->ifcL1VisualState;
|
||||
}
|
||||
break;
|
||||
|
||||
case DivaStateIfcState_LAYER2_STATE:
|
||||
state->ifcL2VisualState = (strcmp ("'Layer2 UP'", v) == 0) ? DivaStatusIfcL2OK : DivaStatusIfcL2Error;
|
||||
if (state->ifcType == DivaStatusIfcPri) {
|
||||
state->ifcL2State = state->ifcL2VisualState;
|
||||
}
|
||||
break;
|
||||
|
||||
case DivaStateIfcState_D1_X_FRAMES:
|
||||
state->ifcTxDStatistics.Frames = (unsigned int)atol(v);
|
||||
break;
|
||||
case DivaStateIfcState_D1_X_BYTES:
|
||||
state->ifcTxDStatistics.Bytes = (unsigned int)atol(v);
|
||||
break;
|
||||
case DivaStateIfcState_D1_X_ERRORS:
|
||||
state->ifcTxDStatistics.Errors = (unsigned int)atol(v);
|
||||
break;
|
||||
case DivaStateIfcState_D1_R_FRAMES:
|
||||
state->ifcRxDStatistics.Frames = (unsigned int)atol(v);
|
||||
break;
|
||||
case DivaStateIfcState_D1_R_BYTES:
|
||||
state->ifcRxDStatistics.Bytes = (unsigned int)atol(v);
|
||||
break;
|
||||
case DivaStateIfcState_D1_R_ERRORS:
|
||||
state->ifcRxDStatistics.Errors = (unsigned int)atol(v);
|
||||
break;
|
||||
|
||||
case DivaStateIfcState_MAX_TEMPERATURE:
|
||||
state->maxTemperature = (unsigned int)atoi(v);
|
||||
break;
|
||||
case DivaStateIfcState_TEMPERATURE:
|
||||
state->currentTemperature = (unsigned int)atoi(v);
|
||||
break;
|
||||
|
||||
case DivaStateIfcState_HARDWARE_STATE:
|
||||
if (strcmp("'Active'", v) == 0)
|
||||
state->hwState = DivaStateHwStateActive;
|
||||
else if (strcmp("'Inactive'", v) == 0)
|
||||
state->hwState = DivaStateHwStateInactive;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_free (data);
|
||||
|
||||
if ((data = diva_status_read_file(controller, DIVA_READ_ALARM_FILE)) != 0) {
|
||||
state->ifcAlarms.Red = strcmp("TRUE", data) == 0;
|
||||
ast_free(data);
|
||||
}
|
||||
if ((data = diva_status_read_file(controller, DIVA_YELLOW_ALARM_FILE)) != 0) {
|
||||
state->ifcAlarms.Yellow = strcmp("TRUE", data) == 0;
|
||||
ast_free(data);
|
||||
}
|
||||
if ((data = diva_status_read_file(controller, DIVA_BLUE_ALARM_FILE)) != 0) {
|
||||
state->ifcAlarms.Blue = strcmp("TRUE", data) == 0;
|
||||
ast_free(data);
|
||||
}
|
||||
if ((data = diva_status_read_file(controller, DIVA_SERIAL_FILE)) != 0) {
|
||||
state->serialNumber = (unsigned int)(atol(data)) & 0x00ffffff;
|
||||
ast_free(data);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
chan_capi interface
|
||||
*/
|
||||
diva_status_interface_state_t diva_status_get_interface_state(int controller)
|
||||
{
|
||||
diva_status_ifc_state_t state;
|
||||
int ret;
|
||||
|
||||
ret = diva_status_get_controller_state(controller, &state);
|
||||
|
||||
if ((ret != 0) ||
|
||||
(state.ifcType != DivaStatusIfcPri) ||
|
||||
(state.ifcL1State == DivaStatusIfcL2DoNotApply) ||
|
||||
(state.hwState == DivaStatusHwStateUnknown)) {
|
||||
return (DivaStatusInterfaceStateNotAvailable);
|
||||
}
|
||||
|
||||
if ((state.ifcAlarms.Red == 0) &&
|
||||
(state.ifcAlarms.Yellow == 0) &&
|
||||
(state.ifcAlarms.Blue == 0) &&
|
||||
(state.hwState == DivaStateHwStateActive) &&
|
||||
(state.ifcL1State == DivaStatusIfcL1OK)) {
|
||||
return DivaStatusInterfaceStateOK;
|
||||
}
|
||||
|
||||
return DivaStatusInterfaceStateERROR;
|
||||
}
|
||||
|
||||
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state(const diva_status_ifc_state_t* state)
|
||||
{
|
||||
if ((state->ifcType != DivaStatusIfcPri) ||
|
||||
(state->ifcL1State == DivaStatusIfcL2DoNotApply) ||
|
||||
(state->hwState == DivaStatusHwStateUnknown)) {
|
||||
return (DivaStatusInterfaceStateNotAvailable);
|
||||
}
|
||||
|
||||
if ((state->ifcAlarms.Red == 0) &&
|
||||
(state->ifcAlarms.Yellow == 0) &&
|
||||
(state->ifcAlarms.Blue == 0) &&
|
||||
(state->hwState == DivaStateHwStateActive) &&
|
||||
(state->ifcL1State == DivaStatusIfcL1OK)) {
|
||||
return DivaStatusInterfaceStateOK;
|
||||
}
|
||||
|
||||
return DivaStatusInterfaceStateERROR;
|
||||
}
|
||||
|
||||
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state(const diva_status_ifc_state_t* state)
|
||||
{
|
||||
switch(state->hwState) {
|
||||
case DivaStateHwStateActive:
|
||||
return (DivaStatusHardwareStateOK);
|
||||
|
||||
case DivaStateHwStateInactive:
|
||||
return (DivaStatusHardwareStateERROR);
|
||||
|
||||
case DivaStatusHwStateUnknown:
|
||||
default:
|
||||
return (DivaStatusHardwareStateUnknown);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Map CAPI controller to Diva hardware
|
||||
|
||||
\note In most cases chan_capi uses 1:1 mappimg
|
||||
between CAPI controller and Diva hardware
|
||||
|
||||
\todo Read CAPI2DIva mapping table from CAPI
|
||||
*/
|
||||
static int diva_status_map_CAPI2XDI(int capiController)
|
||||
{
|
||||
return ((capiController > 0) ? capiController : -1);
|
||||
}
|
||||
|
||||
int diva_status_available(void)
|
||||
{
|
||||
return (diva_status_active());
|
||||
}
|
||||
|
||||
const char* diva_status_interface_state_name(diva_status_interface_state_t state)
|
||||
{
|
||||
switch(state) {
|
||||
case DivaStatusInterfaceStateOK:
|
||||
return "active";
|
||||
|
||||
case DivaStatusInterfaceStateERROR:
|
||||
return "inactive";
|
||||
|
||||
case DivaStatusInterfaceStateNotAvailable:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* diva_status_hw_state_name(diva_status_hardware_state_t hwState)
|
||||
{
|
||||
switch(hwState) {
|
||||
case DivaStatusHardwareStateOK:
|
||||
return "active";
|
||||
|
||||
case DivaStatusHardwareStateERROR:
|
||||
return "not running";
|
||||
|
||||
case DivaStatusHardwareStateUnknown:
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* pbxcli_get_visual_ifc_state(const diva_status_ifc_state_t* state)
|
||||
{
|
||||
diva_status_interface_state_t ifcState;
|
||||
|
||||
switch (state->ifcType) {
|
||||
case DivaStatusIfcBri: /* Functional state is always unknown, probably L1/L2 activated on demand, \todo read L2 config */
|
||||
if (state->hwState == DivaStateHwStateActive &&
|
||||
state->ifcL1VisualState == DivaStatusIfcL1OK &&
|
||||
state->ifcL2VisualState == DivaStatusIfcL2OK) {
|
||||
ifcState = DivaStatusInterfaceStateOK;
|
||||
} else {
|
||||
ifcState = diva_status_get_interface_state_from_idi_state (state);
|
||||
}
|
||||
break;
|
||||
|
||||
case DivaStatusIfcAnalog: /* \todo implementation */
|
||||
ifcState = diva_status_get_interface_state_from_idi_state (state);
|
||||
break;
|
||||
|
||||
case DivaStatusIfcPri: /* Functional state == visual state */
|
||||
default:
|
||||
ifcState = diva_status_get_interface_state_from_idi_state (state);
|
||||
break;
|
||||
}
|
||||
|
||||
return (diva_status_interface_state_name(ifcState));
|
||||
}
|
||||
|
||||
static const char* pbxcli_get_visual_ifc_l1_state(const diva_status_ifc_state_t* state)
|
||||
{
|
||||
const char* ret = "-";
|
||||
|
||||
if (state->hwState == DivaStatusHardwareStateOK) {
|
||||
switch (state->ifcType) {
|
||||
case DivaStatusIfcPri: /* Functional state == visual state */
|
||||
ret = (state->ifcL1State == DivaStatusIfcL1OK) ? "On" : "Off";
|
||||
break;
|
||||
case DivaStatusIfcBri:
|
||||
ret = (state->ifcL1VisualState == DivaStatusIfcL1OK) ? "On" : "Off"; /* Functional state != visual state */
|
||||
break;
|
||||
case DivaStatusIfcAnalog: /* \todo implementation */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static const char* pbxcli_get_visual_ifc_l2_state(const diva_status_ifc_state_t* state)
|
||||
{
|
||||
const char* ret = "-";
|
||||
|
||||
if (state->hwState == DivaStatusHardwareStateOK) {
|
||||
switch (state->ifcType) {
|
||||
case DivaStatusIfcPri: /* Functional state == visual state */
|
||||
ret = (state->ifcL2State == DivaStatusIfcL2OK) ? "On" : "Off";
|
||||
break;
|
||||
case DivaStatusIfcBri:
|
||||
ret = (state->ifcL2VisualState == DivaStatusIfcL2OK) ? "On" : "Off"; /* Functional state != visual state */
|
||||
break;
|
||||
case DivaStatusIfcAnalog: /* \todo implementation */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
char *pbxcli_capi_ifc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
int pbxcli_capi_ifc_status(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
diva_entity_link_t* link;
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " ifcstate";
|
||||
e->usage = diva_status_ifc_state_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
if ( diva_q_get_head(&controller_q) == NULL) {
|
||||
ast_cli(fd, "There are no interraces in " CC_MESSAGE_NAME " instance.\n");
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ast_cli(fd, CC_MESSAGE_NAME " interfaces\n");
|
||||
ast_cli(fd, "%s %-9s%-4s%-4s%-4s%-7s%-5s%8s%12s%12s%12s%12s\n",
|
||||
"INTERFACE", "State", "L1", "L2", "RED", "YELLOW", "BLUE", "D-Rx-Frames", "D-Rx-Bytes","D-Tx-Frames", "D-Tx-Bytes", "D-Errors");
|
||||
|
||||
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
||||
diva_status_ifc_state_t* state = &controllerState->state[controllerState->currentState];
|
||||
ast_cli(fd, "ISDN%-3d%-2s %-9s%-4s%-4s%-4s%-7s%-3s %12d %11d %11d %11d %11d\n",
|
||||
controllerState->capiController, "",
|
||||
pbxcli_get_visual_ifc_state(state),
|
||||
pbxcli_get_visual_ifc_l1_state(state),
|
||||
pbxcli_get_visual_ifc_l2_state(state),
|
||||
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
||||
(state->ifcAlarms.Red != 0 ? "On" : "Off") : "-",
|
||||
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
||||
(state->ifcAlarms.Yellow != 0 ? "On" : "Off") : "-",
|
||||
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
||||
(state->ifcAlarms.Blue != 0 ? "On" : "Off") : "-",
|
||||
state->ifcRxDStatistics.Frames, state->ifcRxDStatistics.Bytes,
|
||||
state->ifcTxDStatistics.Frames, state->ifcTxDStatistics.Bytes,
|
||||
state->ifcRxDStatistics.Errors + state->ifcTxDStatistics.Errors
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return CLI_SUCCESS;
|
||||
#else
|
||||
return RESULT_SUCCESS;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Declares interface to access diva management file system
|
||||
*/
|
||||
|
||||
#ifndef __DIVA_STATUS_H__
|
||||
#define __DIVA_STATUS_H__
|
||||
|
||||
typedef enum _diva_status_ifc_type {
|
||||
DivaStatusIfcNotPri = 0,
|
||||
DivaStatusIfcPri,
|
||||
DivaStatusIfcBri,
|
||||
DivaStatusIfcAnalog
|
||||
} diva_status_ifc_type_t;
|
||||
|
||||
typedef struct _diva_status_ifc_alarms {
|
||||
int Red;
|
||||
int Blue;
|
||||
int Yellow;
|
||||
} diva_status_ifc_alarms_t;
|
||||
|
||||
typedef enum _diva_status_ifc_l1_state {
|
||||
DivaStatusIfcL1DoNotApply = 0,
|
||||
DivaStatusIfcL1OK,
|
||||
DivaStatusIfcL1Error
|
||||
} diva_status_ifc_l1_state_t;
|
||||
|
||||
typedef enum _diva_status_ifc_l2_state {
|
||||
DivaStatusIfcL2DoNotApply = 0,
|
||||
DivaStatusIfcL2OK,
|
||||
DivaStatusIfcL2Error
|
||||
} diva_status_ifc_l2_state_t;
|
||||
|
||||
typedef enum _diva_status_ifc_hw_state {
|
||||
DivaStatusHwStateUnknown = 0,
|
||||
DivaStateHwStateActive = 1,
|
||||
DivaStateHwStateInactive = 2
|
||||
} diva_status_ifc_hw_state_t;
|
||||
|
||||
typedef struct _diva_status_ifc_statistics {
|
||||
unsigned int Frames;
|
||||
unsigned int Bytes;
|
||||
unsigned int Errors;
|
||||
} diva_status_ifc_statistics_t;
|
||||
|
||||
typedef struct _diva_status_ifc_state {
|
||||
diva_status_ifc_type_t ifcType;
|
||||
diva_status_ifc_hw_state_t hwState;
|
||||
diva_status_ifc_alarms_t ifcAlarms;
|
||||
diva_status_ifc_l1_state_t ifcL1State;
|
||||
diva_status_ifc_l2_state_t ifcL2State;
|
||||
diva_status_ifc_l1_state_t ifcL1VisualState;
|
||||
diva_status_ifc_l2_state_t ifcL2VisualState;
|
||||
diva_status_ifc_statistics_t ifcRxDStatistics;
|
||||
diva_status_ifc_statistics_t ifcTxDStatistics;
|
||||
unsigned int serialNumber;
|
||||
unsigned int maxTemperature;
|
||||
unsigned int currentTemperature;
|
||||
} diva_status_ifc_state_t;
|
||||
|
||||
#define DIVA_STATUS_EVENT_L1 0x00000001U
|
||||
#define DIVA_STATUS_EVENT_L2 0x00000002U
|
||||
#define DIVA_STATUS_EVENT_ALARMS 0x00000004U
|
||||
#define DIVA_STATUS_EVENT_STATISTICS 0x00000008U
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Interface to chan_capi
|
||||
*/
|
||||
|
||||
#ifndef __DIVA_STATUS_IFC_H__
|
||||
#define __DIVA_STATUS_IFC_H__
|
||||
|
||||
typedef enum _diva_status_interface_state {
|
||||
DivaStatusInterfaceStateNotAvailable = 0,
|
||||
DivaStatusInterfaceStateOK = 1,
|
||||
DivaStatusInterfaceStateERROR = -1,
|
||||
} diva_status_interface_state_t;
|
||||
|
||||
typedef enum _diva_status_hardware_state {
|
||||
DivaStatusHardwareStateUnknown = 0, /*! /brief divalog is not running or old version of divalog */
|
||||
DivaStatusHardwareStateOK = 1, /*! /brief hardware status veriefied and OK */
|
||||
DivaStatusHardwareStateERROR = -1 /*! /brief hardware status verified and not OK */
|
||||
} diva_status_hardware_state_t;
|
||||
|
||||
/*!
|
||||
\brief Check if Diva interface is available
|
||||
*/
|
||||
int diva_status_available(void);
|
||||
|
||||
typedef void (*diva_status_changed_cb_proc_t)(int controller, diva_status_interface_state_t state);
|
||||
typedef void (*diva_hwstatus_changed_cb_proc_t)(int controller, diva_status_hardware_state_t hwstate);
|
||||
|
||||
/*!
|
||||
\brief activate event based status notifications
|
||||
|
||||
\param fn called if interface state changes, includes hardware state
|
||||
|
||||
\param hwfn called if hardware status changed, hardware state only, used for processing of IP media streams by resource/chat commands
|
||||
*/
|
||||
diva_status_interface_state_t diva_status_init_interface(int controller,
|
||||
diva_status_hardware_state_t* hwState,
|
||||
diva_status_changed_cb_proc_t fn,
|
||||
diva_hwstatus_changed_cb_proc_t hwfn);
|
||||
/*!
|
||||
\brief deactivate event based status notifications
|
||||
*/
|
||||
void diva_status_cleanup_interface(int controller);
|
||||
/*!
|
||||
\brief retrieve file handle to be used in async
|
||||
I/O operations
|
||||
*/
|
||||
int diva_status_get_waitable_object(void);
|
||||
/*!
|
||||
\brief process status change events
|
||||
*/
|
||||
void diva_status_process_events(void);
|
||||
|
||||
/*!
|
||||
\brief Retrieve state of interface
|
||||
DivaStatusInterfaceStateNotAvailable - ignore state
|
||||
DivaStatusInterfaceStateOK - interface state verified and OK
|
||||
DivaStatusInterfaceStateERROR - interface state verified and
|
||||
can not be used to create calls
|
||||
*/
|
||||
diva_status_interface_state_t diva_status_get_interface_state(int controller);
|
||||
|
||||
const char* diva_status_interface_state_name(diva_status_interface_state_t state);
|
||||
const char* diva_status_hw_state_name(diva_status_hardware_state_t hwState);
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
char *pbxcli_capi_ifc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
#else
|
||||
int pbxcli_capi_ifc_status(int fd, int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#define CC_CLI_TEXT_IFC_STATUSINFO "Show " CC_MESSAGE_BIGNAME " interface info"
|
||||
#ifndef CC_AST_HAS_VERSION_1_6
|
||||
extern char diva_status_ifc_state_usage[];
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DIVA_STATUS_PARAMETERS_H__
|
||||
#define __DIVA_STATUS_PARAMETERS_H__
|
||||
|
||||
/*! \brief ifcstate
|
||||
*/
|
||||
typedef enum _diva_state_ifcstate_parameters {
|
||||
DivaStateIfcState_LAYER1_STATE = 0,
|
||||
DivaStateIfcState_LAYER2_STATE,
|
||||
DivaStateIfcState_INC_CALLS,
|
||||
DivaStateIfcState_INC_CONNECTED,
|
||||
DivaStateIfcState_INC_USER_BUSY,
|
||||
DivaStateIfcState_INC_CALL_REJECTED,
|
||||
DivaStateIfcState_INC_WRONG_NUMBER,
|
||||
DivaStateIfcState_INC_INCOMPATIBLE_DST,
|
||||
DivaStateIfcState_INC_OUT_OF_ORDER,
|
||||
DivaStateIfcState_INC_IGNORED,
|
||||
DivaStateIfcState_OUT_CALLS,
|
||||
DivaStateIfcState_OUT_CONNECTED,
|
||||
DivaStateIfcState_OUT_USER_BUSY,
|
||||
DivaStateIfcState_OUT_NO_ANSWER,
|
||||
DivaStateIfcState_OUT_WRONG_NUMBER,
|
||||
DivaStateIfcState_OUT_CALL_REJECTED,
|
||||
DivaStateIfcState_OUT_OTHER_FAILURES,
|
||||
DivaStateIfcState_MDM_DISC_NORMAL,
|
||||
DivaStateIfcState_MDM_DISC_UNSPECIFIED,
|
||||
DivaStateIfcState_MDM_DISC_BUSY_TONE,
|
||||
DivaStateIfcState_MDM_DISC_CONGESTION,
|
||||
DivaStateIfcState_MDM_DISC_CARR_WAIT,
|
||||
DivaStateIfcState_MDM_DISC_TRN_TIMEOUT,
|
||||
DivaStateIfcState_MDM_DISC_INCOMPAT,
|
||||
DivaStateIfcState_MDM_DISC_FRAME_REJ,
|
||||
DivaStateIfcState_MDM_DISC_V42BIS,
|
||||
DivaStateIfcState_FAX_DISC_NORMAL,
|
||||
DivaStateIfcState_FAX_DISC_NOT_IDENT,
|
||||
DivaStateIfcState_FAX_DISC_NO_RESPONSE,
|
||||
DivaStateIfcState_FAX_DISC_RETRIES,
|
||||
DivaStateIfcState_FAX_DISC_UNEXP_MSG,
|
||||
DivaStateIfcState_FAX_DISC_NO_POLLING,
|
||||
DivaStateIfcState_FAX_DISC_TRAINING,
|
||||
DivaStateIfcState_FAX_DISC_UNEXPECTED,
|
||||
DivaStateIfcState_FAX_DISC_APPLICATION,
|
||||
DivaStateIfcState_FAX_DISC_INCOMPAT,
|
||||
DivaStateIfcState_FAX_DISC_NO_COMMAND,
|
||||
DivaStateIfcState_FAX_DISC_LONG_MSG,
|
||||
DivaStateIfcState_FAX_DISC_SUPERVISOR,
|
||||
DivaStateIfcState_FAX_DISC_SUB_SEP_PWD,
|
||||
DivaStateIfcState_FAX_DISC_INVALID_MSG,
|
||||
DivaStateIfcState_FAX_DISC_PAGE_CODING,
|
||||
DivaStateIfcState_FAX_DISC_APP_TIMEOUT,
|
||||
DivaStateIfcState_FAX_DISC_UNSPECIFIED,
|
||||
DivaStateIfcState_B1_X_FRAMES,
|
||||
DivaStateIfcState_B1_X_BYTES,
|
||||
DivaStateIfcState_B1_X_ERRORS,
|
||||
DivaStateIfcState_B1_R_FRAMES,
|
||||
DivaStateIfcState_B1_R_BYTES,
|
||||
DivaStateIfcState_B1_R_ERRORS,
|
||||
DivaStateIfcState_B2_X_FRAMES,
|
||||
DivaStateIfcState_B2_X_BYTES,
|
||||
DivaStateIfcState_B2_X_ERRORS,
|
||||
DivaStateIfcState_B2_R_FRAMES,
|
||||
DivaStateIfcState_B2_R_BYTES,
|
||||
DivaStateIfcState_B2_R_ERRORS,
|
||||
DivaStateIfcState_D1_X_FRAMES,
|
||||
DivaStateIfcState_D1_X_BYTES,
|
||||
DivaStateIfcState_D1_X_ERRORS,
|
||||
DivaStateIfcState_D1_R_FRAMES,
|
||||
DivaStateIfcState_D1_R_BYTES,
|
||||
DivaStateIfcState_D1_R_ERRORS,
|
||||
DivaStateIfcState_D2_X_FRAMES,
|
||||
DivaStateIfcState_D2_X_BYTES,
|
||||
DivaStateIfcState_D2_X_ERRORS,
|
||||
DivaStateIfcState_D2_R_FRAMES,
|
||||
DivaStateIfcState_D2_R_BYTES,
|
||||
DivaStateIfcState_D2_R_ERRORS,
|
||||
DivaStateIfcState_INITIAL_TEMPERATURE,
|
||||
DivaStateIfcState_MIN_TEMPERATURE,
|
||||
DivaStateIfcState_MAX_TEMPERATURE,
|
||||
DivaStateIfcState_TEMPERATURE,
|
||||
DivaStateIfcState_DSPSTATE,
|
||||
DivaStateIfcState_FAX_TX_PAGES_TOTAL,
|
||||
DivaStateIfcState_FAX_TX_PAGES_RETRAIN,
|
||||
DivaStateIfcState_FAX_TX_PAGES_REJECT,
|
||||
DivaStateIfcState_FAX_RX_PAGES_TOTAL,
|
||||
DivaStateIfcState_FAX_RX_PAGES_RETRAIN,
|
||||
DivaStateIfcState_FAX_RX_PAGES_REJECT,
|
||||
DivaStateIfcState_OUT_ABANDONED,
|
||||
DivaStateIfcState_IN_ABANDONED,
|
||||
DivaStateIfcState_HARDWARE_STATE,
|
||||
DivaStateIfcState_Max
|
||||
} diva_state_ifcstate_parameters_t;
|
||||
|
||||
typedef enum diva_state_ifc_config_parameters {
|
||||
DivaStateIfcConfig_TYPE = 0,
|
||||
DivaStateIfcConfig_CHANNELS,
|
||||
DivaStateIfcConfig_PROTOCOL,
|
||||
DivaStateIfcConfig_NT_MODE,
|
||||
DivaStateIfcConfig_POINTTOPOINT,
|
||||
DivaStateIfcConfig_INTERFACENR,
|
||||
DivaStateIfcConfig_BOARDREVISION,
|
||||
DivaStateIfcConfig_SUBFUNCTION,
|
||||
DivaStateIfcConfig_SUBDEVICE,
|
||||
DivaStateIfcConfig_PROTOCOLBUILD,
|
||||
DivaStateIfcConfig_DSPCODEBUILD,
|
||||
DivaStateIfcConfig_ANALOGCHANNELS,
|
||||
DivaStateIfcConfig_PRI,
|
||||
DivaStateIfcConfig_PCIDMA,
|
||||
DivaStateIfcConfig_ADAPTERTYPE,
|
||||
DivaStateIfcConfig_LAW,
|
||||
DivaStateIfcConfig_Max
|
||||
} diva_state_ifc_config_parameters_t;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,431 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010-2011
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Implements to access Diva streaming
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_streaming_messages.h"
|
||||
#include "diva_streaming_vector.h"
|
||||
#include "diva_streaming_manager.h"
|
||||
#include "chan_capi_divastreaming_utils.h"
|
||||
|
||||
/*
|
||||
LOCALS
|
||||
*/
|
||||
static int diva_streaming_disabled;
|
||||
AST_MUTEX_DEFINE_STATIC(stream_write_lock);
|
||||
|
||||
static diva_entity_queue_t diva_streaming_new; /* protected by stream_write_lock, new streams */
|
||||
|
||||
int capi_DivaStreamingSupported (unsigned controller)
|
||||
{
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
int waitcount = 50;
|
||||
unsigned char manbuf[CAPI_MANUFACTURER_LEN];
|
||||
_cmsg CMSG;
|
||||
int ret = 0;
|
||||
|
||||
if (capi20_get_manufacturer(controller, manbuf) == NULL) {
|
||||
goto done;
|
||||
}
|
||||
if ((strstr((char *)manbuf, "Eicon") == 0) &&
|
||||
(strstr((char *)manbuf, "Dialogic") == 0)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, controller, get_capi_MessageNumber(),
|
||||
"dw(bs)", _DI_MANU_ID, _DI_STREAM_CTRL, 2, "");
|
||||
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
while (waitcount) {
|
||||
error = capidev_check_wait_get_cmsg(&CMSG);
|
||||
|
||||
if (IS_MANUFACTURER_CONF(&CMSG) && (CMSG.ManuID == _DI_MANU_ID) &&
|
||||
((CMSG.Class & 0xffff) == _DI_STREAM_CTRL)) {
|
||||
error = (MESSAGE_EXCHANGE_ERROR)(CMSG.Class >> 16);
|
||||
ret = (error == 0);
|
||||
break;
|
||||
}
|
||||
usleep(30000);
|
||||
waitcount--;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int divaStreamingMessageRx (void* user_context, dword message, dword length, const struct _diva_streaming_vector* v, dword nr_v)
|
||||
{
|
||||
diva_stream_scheduling_entry_t* pE = (diva_stream_scheduling_entry_t*)user_context;
|
||||
dword message_type = (message & 0xff);
|
||||
|
||||
if (message_type == 0) { /* IDI message */
|
||||
dword offset = 0;
|
||||
diva_streaming_vector_t vind[8];
|
||||
byte Ind = 0;
|
||||
int vind_nr = 0;
|
||||
int process_indication;
|
||||
|
||||
do {
|
||||
vind_nr = sizeof(vind)/sizeof(vind[0]);
|
||||
offset = diva_streaming_get_indication_data (offset, message, length, v, nr_v, &Ind, vind, &vind_nr);
|
||||
|
||||
process_indication = (diva_streaming_idi_supported_ind (Ind, vind_nr != 0, vind_nr != 0 ? (byte*)vind->data : (byte*)"") != 0);
|
||||
|
||||
if (likely(process_indication != 0)) {
|
||||
if (likely(Ind == 8)) {
|
||||
if (likely(pE->i != 0 && pE->i->NCCI != 0)) {
|
||||
if (pE->i->virtualBridgePeer != 0) {
|
||||
if (pE->i->bridgePeer != 0) {
|
||||
struct capi_pvt* bridgePeer = pE->i->bridgePeer;
|
||||
if (bridgePeer->NCCI != 0 && bridgePeer->diva_stream_entry != 0 &&
|
||||
bridgePeer->diva_stream_entry->diva_stream_state == DivaStreamActive &&
|
||||
bridgePeer->diva_stream_entry->diva_stream->get_tx_in_use (bridgePeer->diva_stream_entry->diva_stream) < 512 &&
|
||||
bridgePeer->diva_stream_entry->diva_stream->get_tx_free (bridgePeer->diva_stream_entry->diva_stream) >
|
||||
2*CAPI_MAX_B3_BLOCK_SIZE+128) {
|
||||
dword i = 0, k = 0, b3len;
|
||||
byte b3buf[CAPI_MAX_B3_BLOCK_SIZE];
|
||||
b3len = diva_streaming_read_vector_data(vind, vind_nr, &i, &k, b3buf, CAPI_MAX_B3_BLOCK_SIZE);
|
||||
bridgePeer->diva_stream_entry->diva_stream->write (bridgePeer->diva_stream_entry->diva_stream,
|
||||
8U << 8 | DIVA_STREAM_MESSAGE_TX_IDI_REQUEST,
|
||||
b3buf, b3len);
|
||||
bridgePeer->diva_stream_entry->diva_stream->flush_stream(bridgePeer->diva_stream_entry->diva_stream);
|
||||
} else {
|
||||
if (bridgePeer->NCCI != 0 && bridgePeer->diva_stream_entry != 0 &&
|
||||
bridgePeer->diva_stream_entry->diva_stream_state == DivaStreamActive) {
|
||||
DBG_ERR(("%s PLCI %04x discarded bridge packet free: %u in use: %u",
|
||||
pE->i->name, pE->i->PLCI & 0xffffU,
|
||||
bridgePeer->diva_stream_entry->diva_stream->get_tx_free (bridgePeer->diva_stream_entry->diva_stream),
|
||||
bridgePeer->diva_stream_entry->diva_stream->get_tx_in_use (bridgePeer->diva_stream_entry->diva_stream)))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
capidev_handle_data_b3_indication_vector (pE->i, vind, vind_nr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dword i = 0, k = 0;
|
||||
word data_length;
|
||||
byte ind_data_buffer[2048+512];
|
||||
data_length = (word)diva_streaming_read_vector_data (vind, vind_nr, &i, &k, ind_data_buffer, sizeof(ind_data_buffer));
|
||||
|
||||
DBG_TRC(("Ind: %02x length:%u", Ind, data_length))
|
||||
}
|
||||
}
|
||||
} while (offset != 0);
|
||||
} else if (message_type == 0xff) { /* System message */
|
||||
switch ((byte)(message >> 8)) {
|
||||
case DIVA_STREAM_MESSAGE_INIT: /* Stream active */
|
||||
if (pE->PLCI == 0 && pE->i != 0) {
|
||||
pE->PLCI = pE->i->PLCI;
|
||||
}
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream active (PLCI=%#x)\n", pE->vname, pE->PLCI);
|
||||
if (pE->diva_stream_state == DivaStreamCreated) {
|
||||
pE->diva_stream_state = DivaStreamActive;
|
||||
} else if (pE->diva_stream_state == DivaStreamCancelSent) {
|
||||
pE->diva_stream->release_stream(pE->diva_stream);
|
||||
pE->i = 0;
|
||||
pE->diva_stream_state = DivaStreamDisconnectSent;
|
||||
}
|
||||
break;
|
||||
|
||||
case DIVA_STREAM_MESSAGE_RX_TX_ACK: /* Resolved Tx flow control */
|
||||
/* cc_verbose(4, 1, "%s: stream tx ack (PLCI=%#x)\n", pE->vname, pE->PLCI); */
|
||||
break;
|
||||
|
||||
case DIVA_STREAM_MESSAGE_SYNC_ACK: /* Sync ack request acknowledge */
|
||||
cc_verbose(4, 1, "%s: stream sync ack (PLCI=%#x, sequence=%08x)\n", pE->vname, pE->PLCI, length);
|
||||
break;
|
||||
|
||||
case DIVA_STREAM_MESSAGE_RELEASE_ACK: /* Release stream acknowledge */
|
||||
pE->diva_stream_state = DivaStreamDisconnected;
|
||||
pE->diva_stream = 0;
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream released (PLCI=%#x)\n", pE->vname, pE->PLCI);
|
||||
break;
|
||||
|
||||
case DIVA_STREAM_MESSAGE_INIT_ERROR: /* Failed to initialize stream */
|
||||
pE->diva_stream_state = DivaStreamDisconnected;
|
||||
pE->diva_stream = 0;
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream init error (PLCI=%#x, error=%d)\n", pE->vname, pE->PLCI, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: stream unknown system message (PLCI=%#x, message=%08x)\n", pE->vname, pE->PLCI, message);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cc_verbose(3, 0, VERBOSE_PREFIX_2 "%s: unknown stream message (PLCI=%#x, message=%08x)\n", pE->vname, pE->PLCI, message);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create Diva stream
|
||||
*
|
||||
*/
|
||||
void capi_DivaStreamingOn(struct capi_pvt *i, byte streamCommand, _cword messageNumber)
|
||||
{
|
||||
diva_stream_scheduling_entry_t* pE;
|
||||
int ret;
|
||||
char trace_ident[8];
|
||||
unsigned int effectivePLCI;
|
||||
|
||||
if (diva_streaming_disabled)
|
||||
return;
|
||||
|
||||
pE = ast_malloc (sizeof(*pE));
|
||||
if (pE == 0)
|
||||
return;
|
||||
|
||||
snprintf (trace_ident, sizeof(trace_ident), "C%02x", (byte)i->PLCI);
|
||||
trace_ident[sizeof(trace_ident)-1] = 0;
|
||||
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
|
||||
ret = diva_stream_create (&pE->diva_stream, NULL, 255, divaStreamingMessageRx, pE, trace_ident);
|
||||
|
||||
if (ret == 0) {
|
||||
static byte addie[] = { 0x2d /* UID */, 0x01, 0x00, 0x04 /* BC */, 0x04, 0x0, 0x0, 0x0, 0x00 /* 0x20 DMA polling */, 0 /* END */};
|
||||
byte* description = (byte*)pE->diva_stream->description (pE->diva_stream, addie, (byte)sizeof(addie));
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
|
||||
description[1] = streamCommand;
|
||||
|
||||
description[3] |= 0x01;
|
||||
|
||||
if (streamCommand == 0) {
|
||||
messageNumber = get_capi_MessageNumber();
|
||||
effectivePLCI = i->PLCI;
|
||||
} else {
|
||||
/*
|
||||
PLCI still not assigned. Send to controller and tag with message number
|
||||
where command receives effective
|
||||
*/
|
||||
effectivePLCI = i->controller;
|
||||
}
|
||||
|
||||
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, effectivePLCI, messageNumber,
|
||||
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
|
||||
if (error == 0) {
|
||||
pE->diva_stream_state = DivaStreamCreated;
|
||||
pE->PLCI = i->PLCI;
|
||||
pE->i = i;
|
||||
i->diva_stream_entry = pE;
|
||||
memcpy (pE->vname, i->vname, MIN(sizeof(pE->vname), sizeof(i->vname)));
|
||||
pE->vname[sizeof(pE->vname)-1] = 0;
|
||||
pE->rx_flow_control = 0;
|
||||
pE->tx_flow_control = 0;
|
||||
diva_q_add_tail (&diva_streaming_new, &pE->link);
|
||||
} else {
|
||||
pE->diva_stream->release (pE->diva_stream);
|
||||
ast_free (pE);
|
||||
}
|
||||
}
|
||||
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove stream info
|
||||
*
|
||||
* To remove stream from one active connection:
|
||||
* remove stream info
|
||||
* disconnect B3
|
||||
* remove stream
|
||||
* select_b
|
||||
*/
|
||||
void capi_DivaStreamingRemoveInfo(struct capi_pvt *i)
|
||||
{
|
||||
byte description[] = { 2, 0, 0 };
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
int send;
|
||||
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
send = i->diva_stream_entry != 0;
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
|
||||
if (send != 0)
|
||||
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, i->PLCI, get_capi_MessageNumber(),
|
||||
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Send empty stream to inform no Diva streaming is used for this PLCI
|
||||
*/
|
||||
void capi_DivaStreamingStreamNotUsed(struct capi_pvt *i, byte streamCommand, _cword messageNumber)
|
||||
{
|
||||
byte description[] = { 0x04, 0x00, 0x02, 0x00, 0x00 };
|
||||
unsigned int effectivePLCI;
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
|
||||
description[1] = streamCommand;
|
||||
|
||||
if (streamCommand == 0) {
|
||||
messageNumber = get_capi_MessageNumber();
|
||||
effectivePLCI = i->PLCI;
|
||||
} else {
|
||||
/*
|
||||
PLCI still not assigned. Send to controller and tag with message number
|
||||
where command receives effective
|
||||
*/
|
||||
effectivePLCI = i->controller;
|
||||
}
|
||||
|
||||
error = capi_sendf (NULL, 0, CAPI_MANUFACTURER_REQ, effectivePLCI, messageNumber,
|
||||
"dws", _DI_MANU_ID, _DI_STREAM_CTRL, description);
|
||||
}
|
||||
|
||||
void capi_DivaStreamingRemove(struct capi_pvt *i)
|
||||
{
|
||||
diva_stream_scheduling_entry_t* pE = i->diva_stream_entry;
|
||||
int send_cancel = 0;
|
||||
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
pE = i->diva_stream_entry;
|
||||
if (pE != 0) {
|
||||
i->diva_stream_entry = 0;
|
||||
pE->i = 0;
|
||||
if (pE->diva_stream_state == DivaStreamCreated) {
|
||||
|
||||
if (i->NCCI != 0) {
|
||||
/*
|
||||
If NCCI is not sen then this is no possibility to send cancel request
|
||||
to queued in the IDI L2 streaming info. But in user mode this is OK,
|
||||
if removing PLCI CAPI removes networking entity and this operation
|
||||
causes cancellation of create streaming request.
|
||||
Timeout is only for the rare case where create streaming request was newer
|
||||
sent to hardware.
|
||||
*/
|
||||
send_cancel = 1;
|
||||
}
|
||||
pE->diva_stream_state = DivaStreamCancelSent;
|
||||
pE->cancel_start = time(NULL) + 5;
|
||||
DBG_LOG(("stream cancelled [%p]", pE->diva_stream))
|
||||
} else if (pE->diva_stream_state == DivaStreamActive) {
|
||||
pE->diva_stream->release_stream(pE->diva_stream);
|
||||
pE->diva_stream_state = DivaStreamDisconnectSent;
|
||||
}
|
||||
}
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
|
||||
if (send_cancel != 0) {
|
||||
static byte data[] = { 0x8 /* CONTROL */, 0x01 /* CANCEL */};
|
||||
MESSAGE_EXCHANGE_ERROR error;
|
||||
|
||||
error = capi_sendf(NULL, 0, CAPI_DATA_B3_REQ, i->NCCI, get_capi_MessageNumber(),
|
||||
"dwww", data, sizeof(data), 0, 1U << 4);
|
||||
if (likely(error == 0)) {
|
||||
cc_mutex_lock(&i->lock);
|
||||
i->B3count++;
|
||||
cc_mutex_unlock(&i->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This is only one used to access streaming scheduling list routine.
|
||||
This ensures list can be accessed w/o anly locks
|
||||
|
||||
To ensure exclusive access scheduling queue is static function variable
|
||||
*/
|
||||
void divaStreamingWakeup (void)
|
||||
{
|
||||
static diva_entity_queue_t active_streams;
|
||||
diva_entity_link_t* link;
|
||||
time_t current_time = time (NULL);
|
||||
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
while ((link = diva_q_get_head (&diva_streaming_new)) != 0) {
|
||||
diva_stream_scheduling_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_stream_scheduling_entry_t, link);
|
||||
diva_q_remove (&diva_streaming_new, &pE->link);
|
||||
diva_q_add_tail (&active_streams, &pE->link);
|
||||
}
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
|
||||
for (link = diva_q_get_head (&active_streams); likely(link != 0);) {
|
||||
diva_entity_link_t* next = diva_q_get_next(link);
|
||||
diva_stream_scheduling_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_stream_scheduling_entry_t, link);
|
||||
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
pE->diva_stream->wakeup (pE->diva_stream);
|
||||
if (unlikely(pE->diva_stream_state == DivaStreamCancelSent && pE->cancel_start < current_time)) {
|
||||
DBG_LOG(("stream reclaimed [%p]", pE->diva_stream))
|
||||
pE->diva_stream->release (pE->diva_stream);
|
||||
pE->diva_stream_state = DivaStreamDisconnected;
|
||||
pE->diva_stream = 0;
|
||||
}
|
||||
|
||||
if (unlikely(pE->diva_stream == 0)) {
|
||||
diva_q_remove (&active_streams, &pE->link);
|
||||
if (pE->i != 0) {
|
||||
pE->i->diva_stream_entry = 0;
|
||||
}
|
||||
ast_free (pE);
|
||||
}
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
|
||||
link = next;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int capi_DivaStreamingGetStreamInUse(const struct capi_pvt* i)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
capi_DivaStreamLock();
|
||||
if ((i != NULL) && (i->diva_stream_entry != NULL) &&
|
||||
(i->diva_stream_entry->diva_stream_state == DivaStreamActive) &&
|
||||
(i->diva_stream_entry->diva_stream != NULL)) {
|
||||
ret = i->diva_stream_entry->diva_stream->get_tx_in_use (i->diva_stream_entry->diva_stream);
|
||||
}
|
||||
capi_DivaStreamUnLock();
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void capi_DivaStreamLock(void)
|
||||
{
|
||||
cc_mutex_lock(&stream_write_lock);
|
||||
}
|
||||
|
||||
void capi_DivaStreamUnLock(void)
|
||||
{
|
||||
cc_mutex_unlock(&stream_write_lock);
|
||||
}
|
||||
|
||||
void capi_DivaStreamingDisable (void) {
|
||||
diva_streaming_disabled = 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef __DIVA_CAPI_STREAMING_UTILS_H__
|
||||
#define __DIVA_CAPI_STREAMING_UTILS_H__
|
||||
|
||||
extern int capi_DivaStreamingSupported(unsigned controller);
|
||||
extern void capi_DivaStreamingOn(struct capi_pvt *i, unsigned char streamCommand, _cword messageNumber);
|
||||
extern void capi_DivaStreamingStreamNotUsed(struct capi_pvt *i, byte streamCommand, _cword messageNumber);
|
||||
extern void capi_DivaStreamingRemoveInfo(struct capi_pvt *i);
|
||||
extern void capi_DivaStreamingRemove(struct capi_pvt *i);
|
||||
extern void divaStreamingWakeup(void);
|
||||
extern unsigned int capi_DivaStreamingGetStreamInUse(const struct capi_pvt* i);
|
||||
extern void capi_DivaStreamLock(void);
|
||||
extern void capi_DivaStreamUnLock (void);
|
||||
extern void capi_DivaStreamingDisable (void);
|
||||
|
||||
typedef enum _diva_stream_state {
|
||||
DivaStreamCreated = 0,
|
||||
DivaStreamActive = 1,
|
||||
DivaStreamCancelSent = 2,
|
||||
DivaStreamDisconnectSent = 3,
|
||||
DivaStreamDisconnected = 4
|
||||
} diva_stream_state_t;
|
||||
|
||||
typedef struct _diva_stream_scheduling_entry {
|
||||
diva_entity_link_t link;
|
||||
struct _diva_stream *diva_stream;
|
||||
diva_stream_state_t diva_stream_state;
|
||||
struct capi_pvt *i;
|
||||
int rx_flow_control;
|
||||
int tx_flow_control;
|
||||
char vname[CAPI_MAX_STRING]; /* Cached from capi_pvt */
|
||||
dword PLCI; /* Cached from capi_pvt */
|
||||
time_t cancel_start;
|
||||
} diva_stream_scheduling_entry_t;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_DEBUGLIB_H__
|
||||
#define __DIVA_STREAMING_DEBUGLIB_H__
|
||||
|
||||
void diva_runtime_error_message (const char* fmt, ...);
|
||||
void diva_runtime_log_message (const char* fmt, ...);
|
||||
void diva_runtime_trace_message (const char* fmt, ...);
|
||||
void diva_runtime_binary_message (const void* data, unsigned long length);
|
||||
|
||||
#define DBG_ERR(__x__) do { diva_runtime_error_message __x__; } while (0);
|
||||
#define DBG_LOG(__x__) do { diva_runtime_log_message __x__; } while (0);
|
||||
#define DBG_TRC(__x__) do { diva_runtime_trace_message __x__; } while (0);
|
||||
#define DBG_BLK(__x__) do { diva_runtime_binary_message __x__; } while (0);
|
||||
|
||||
#define dbg_init(__a__, __b__, __c__) do { static int initialized; if (initialized == 0) { initialized = 1; diva_runtime_log_message("%s %s %u", __a__, __b__, __c__); } } while (0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_SEGMENT_ALLOC_H__
|
||||
#define __DIVA_SEGMENT_ALLOC_H__
|
||||
|
||||
struct _diva_segment_alloc;
|
||||
struct _diva_segment_alloc_access;
|
||||
|
||||
typedef struct _diva_segment_alloc_access {
|
||||
void (*release)(struct _diva_segment_alloc** ifc);
|
||||
void* (*segment_alloc)(struct _diva_segment_alloc* ifc, dword* lo, dword* hi);
|
||||
void (*segment_free)(struct _diva_segment_alloc* ifc, void* addr, dword lo, dword hi);
|
||||
dword (*get_segment_length)(struct _diva_segment_alloc* ifc);
|
||||
void* (*map_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, int map_host);
|
||||
void* (*umap_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local);
|
||||
int (*write_address)(struct _diva_segment_alloc* ifc, dword lo, dword hi, dword data);
|
||||
void (*resource_removed)(struct _diva_segment_alloc* ifc);
|
||||
} diva_segment_alloc_access_t;
|
||||
|
||||
int diva_create_segment_alloc (void* os_context, struct _diva_segment_alloc** segment_alloc);
|
||||
int diva_destroy_segment_alloc (struct _diva_segment_alloc** segment_alloc);
|
||||
diva_segment_alloc_access_t* diva_get_segment_alloc_ifc (struct _diva_segment_alloc* segment_alloc);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_IDI_HOST_IFC__
|
||||
#define __DIVA_STREAMING_IDI_HOST_IFC__
|
||||
|
||||
/*
|
||||
Write data from host to remote side
|
||||
*/
|
||||
struct _diva_stream;
|
||||
struct _diva_segment_alloc_ifc;
|
||||
struct _diva_streaming_idi_host_ifc_w;
|
||||
struct _diva_streaming_idi_host_ifc_w_access;
|
||||
struct _diva_streaming_idi_host_ifc_r;
|
||||
struct _diva_streaming_idi_host_ifc_r_access;
|
||||
|
||||
|
||||
typedef struct _diva_streaming_idi_host_ifc_w_access {
|
||||
int (*release)(struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
diva_streaming_idi_result_t (*release_stream)(struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
int (*write_message)(struct _diva_streaming_idi_host_ifc_w* ifc,
|
||||
dword info, const void* data, dword data_length);
|
||||
int (*ack)(struct _diva_streaming_idi_host_ifc_w* ifc, dword length);
|
||||
int (*ack_rx)(struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack);
|
||||
int (*write)(struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length);
|
||||
int (*write_indirect)(struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length);
|
||||
int (*update_remote)(struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
dword (*get_in_use)(const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
dword (*get_free)(const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
dword (*get_length)(const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
byte (*description)(struct _diva_streaming_idi_host_ifc_w* ifc, byte* dst, byte max_length);
|
||||
int (*init)(struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info);
|
||||
diva_streaming_idi_result_t (*sync)(struct _diva_streaming_idi_host_ifc_w* ifc, dword ident);
|
||||
diva_streaming_idi_result_t (*trace_ident)(struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
} diva_streaming_idi_host_ifc_w_access_t;
|
||||
|
||||
int diva_streaming_idi_host_ifc_create (struct _diva_streaming_idi_host_ifc_w** ifc,
|
||||
dword number_segments,
|
||||
struct _diva_segment_alloc* segment_alloc,
|
||||
const char* trace_ident);
|
||||
struct _diva_streaming_idi_host_ifc_w_access* diva_streaming_idi_host_ifc_get_access (
|
||||
struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
|
||||
typedef struct _diva_streaming_idi_host_ifc_r_access {
|
||||
int (*release)(struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
int (*wakeup)(struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
byte (*description)(struct _diva_streaming_idi_host_ifc_r* ifc, byte* dst, byte max_length);
|
||||
} diva_streaming_idi_host_ifc_r_access_t;
|
||||
|
||||
int diva_streaming_idi_host_rx_ifc_create (struct _diva_streaming_idi_host_ifc_r** ifc,
|
||||
dword number_segments,
|
||||
struct _diva_segment_alloc* segment_alloc,
|
||||
struct _diva_streaming_idi_host_ifc_w* tx,
|
||||
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc,
|
||||
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc,
|
||||
void* user_context,
|
||||
struct _diva_stream* diva_streaming_manager_ifc,
|
||||
const char* trace_ident);
|
||||
struct _diva_streaming_idi_host_ifc_r_access* diva_streaming_idi_host_rx_ifc_get_access (
|
||||
struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* vim:ts=2:
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "pc.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_streaming_vector.h"
|
||||
#include "diva_streaming_messages.h"
|
||||
#include "diva_streaming_manager.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_segment_alloc_ifc.h"
|
||||
#include "diva_streaming_idi_host_ifc.h"
|
||||
#include "diva_streaming_idi_host_ifc_impl.h"
|
||||
#include "spi_descriptor.h"
|
||||
|
||||
static int diva_streaming_idi_host_ifc_cleanup (struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static int write_message (struct _diva_streaming_idi_host_ifc_w* ifc,
|
||||
dword info,
|
||||
const void* data,
|
||||
dword data_length);
|
||||
static byte description (diva_streaming_idi_host_ifc_w_t* ifc, byte* dst, byte max_length);
|
||||
static int init (struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info);
|
||||
static diva_streaming_idi_result_t sync_req (struct _diva_streaming_idi_host_ifc_w* ifc, dword ident);
|
||||
static int ack_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length);
|
||||
static int ack_rx_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack);
|
||||
static int write_data (struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length);
|
||||
static int write_indirect (struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length);
|
||||
static int update_remote (struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static dword get_in_use (const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static dword get_free (const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static dword get_length (const struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static void write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, const void* data, dword data_length);
|
||||
static void update_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc);
|
||||
static diva_streaming_idi_result_t set_trace_ident (struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
static diva_streaming_idi_result_t release_stream (struct _diva_streaming_idi_host_ifc_w* ifc);
|
||||
|
||||
|
||||
int diva_streaming_idi_host_ifc_create (struct _diva_streaming_idi_host_ifc_w** ifc,
|
||||
dword number_segments,
|
||||
struct _diva_segment_alloc* segment_alloc,
|
||||
const char* trace_ident) {
|
||||
struct _diva_streaming_idi_host_ifc_w* ifc_w = *ifc;
|
||||
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (segment_alloc);
|
||||
dword i;
|
||||
int free_ifc = 0;
|
||||
|
||||
if (ifc_w == 0) {
|
||||
ifc_w = diva_os_malloc (0, sizeof(*ifc_w));
|
||||
free_ifc = 1;
|
||||
}
|
||||
|
||||
if (ifc_w == 0) {
|
||||
DBG_ERR(("failed to create idi w interface [%s]", trace_ident))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset (ifc_w, 0x00, sizeof(*ifc_w));
|
||||
memcpy(ifc_w->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
|
||||
ifc_w->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
|
||||
|
||||
ifc_w->nr_segments = MIN(number_segments, DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS);
|
||||
ifc_w->segment_alloc = segment_alloc;
|
||||
ifc_w->free_ifc = free_ifc;
|
||||
|
||||
for (i = 0; i < ifc_w->nr_segments; i++) {
|
||||
ifc_w->segments[i] = (*(segment_alloc_access->segment_alloc))(segment_alloc,
|
||||
&ifc_w->segment_lo[i],
|
||||
&ifc_w->segment_hi[i]);
|
||||
if (ifc_w->segments[i] == 0) {
|
||||
DBG_ERR(("failed to alloc segment [%s]", trace_ident))
|
||||
diva_streaming_idi_host_ifc_cleanup (ifc_w);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
DBG_TRC(("alloc %p %08x:%08x [%s]", ifc_w->segments[i], ifc_w->segment_lo[i], ifc_w->segment_hi[i], trace_ident))
|
||||
|
||||
ifc_w->segment_length[i] = (*(segment_alloc_access->get_segment_length))(segment_alloc);
|
||||
if (i == 0) {
|
||||
*(volatile dword*)(ifc_w->segments[i]+ifc_w->segment_length[i]-sizeof(dword)) = 0;
|
||||
}
|
||||
|
||||
ifc_w->state.length += ifc_w->segment_length[i];
|
||||
}
|
||||
|
||||
ifc_w->ack_rx = 0;
|
||||
|
||||
ifc_w->state.used_length = 0;
|
||||
ifc_w->state.free_length = ifc_w->state.length;
|
||||
|
||||
ifc_w->state.write_buffer = 0;
|
||||
ifc_w->state.write_buffer_position = 0;
|
||||
ifc_w->state.write_buffer_free = ifc_w->segment_length[ifc_w->state.write_buffer];
|
||||
|
||||
ifc_w->state.acknowledge_buffer = 0;
|
||||
ifc_w->state.acknowledge_buffer_position = 0;
|
||||
|
||||
ifc_w->remote.written = 0;
|
||||
|
||||
ifc_w->access.release = diva_streaming_idi_host_ifc_cleanup;
|
||||
ifc_w->access.release_stream = release_stream;
|
||||
ifc_w->access.write_message = write_message;
|
||||
ifc_w->access.ack = ack_data;
|
||||
ifc_w->access.ack_rx = ack_rx_data;
|
||||
ifc_w->access.write = write_data;
|
||||
ifc_w->access.write_indirect = write_indirect;
|
||||
ifc_w->access.update_remote = update_remote;
|
||||
ifc_w->access.get_in_use = get_in_use;
|
||||
ifc_w->access.get_free = get_free;
|
||||
ifc_w->access.get_length = get_length;
|
||||
ifc_w->access.description = description;
|
||||
ifc_w->access.init = init;
|
||||
ifc_w->access.sync = sync_req;
|
||||
ifc_w->access.trace_ident = set_trace_ident;
|
||||
|
||||
*ifc = ifc_w;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct _diva_streaming_idi_host_ifc_w_access* diva_streaming_idi_host_ifc_get_access (
|
||||
struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
return (&ifc->access);
|
||||
}
|
||||
|
||||
static int diva_streaming_idi_host_ifc_cleanup (struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
|
||||
dword i;
|
||||
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
if (ifc->segments[i] != 0) {
|
||||
(*(segment_alloc_access->segment_free))(ifc->segment_alloc,
|
||||
ifc->segments[i],
|
||||
ifc->segment_lo[i],
|
||||
ifc->segment_hi[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifc->remote_counter_mapped_base != 0) {
|
||||
segment_alloc_access->umap_address (ifc->segment_alloc, ifc->remote_counter_base, 0, ifc->remote_counter_mapped_base);
|
||||
}
|
||||
|
||||
if (ifc->free_ifc != 0) {
|
||||
diva_os_free (0, ifc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void update_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc) {
|
||||
if (ifc->state.write_buffer_free == 0) {
|
||||
ifc->state.write_buffer++;
|
||||
if (ifc->state.write_buffer >= ifc->nr_segments) {
|
||||
ifc->state.write_buffer = 0;
|
||||
}
|
||||
ifc->state.write_buffer_free = ifc->segment_length[ifc->state.write_buffer];
|
||||
ifc->state.write_buffer_position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, const void* data, dword data_length) {
|
||||
const byte* src = (const byte*)data;
|
||||
dword to_write = data_length;
|
||||
|
||||
while (data_length != 0) {
|
||||
dword to_copy = MIN(ifc->state.write_buffer_free, data_length);
|
||||
memcpy (ifc->segments[ifc->state.write_buffer]+ifc->state.write_buffer_position, src, to_copy);
|
||||
src += to_copy;
|
||||
ifc->state.write_buffer_position += to_copy;
|
||||
ifc->state.write_buffer_free -= to_copy;
|
||||
data_length -= to_copy;
|
||||
update_write_buffer (ifc);
|
||||
}
|
||||
|
||||
ifc->state.free_length -= to_write;
|
||||
ifc->state.used_length += to_write;
|
||||
ifc->remote.written += ((int32)to_write);
|
||||
}
|
||||
|
||||
static void align_write_buffer (diva_streaming_idi_host_ifc_w_t* ifc, dword data_length) {
|
||||
dword to_write = data_length;
|
||||
|
||||
while (data_length != 0) {
|
||||
dword to_copy = MIN(ifc->state.write_buffer_free, data_length);
|
||||
ifc->state.write_buffer_position += to_copy;
|
||||
ifc->state.write_buffer_free -= to_copy;
|
||||
data_length -= to_copy;
|
||||
update_write_buffer (ifc);
|
||||
}
|
||||
|
||||
ifc->state.free_length -= to_write;
|
||||
ifc->state.used_length += to_write;
|
||||
ifc->remote.written += ((int32)to_write);
|
||||
}
|
||||
|
||||
static int write_message (struct _diva_streaming_idi_host_ifc_w* ifc,
|
||||
dword info,
|
||||
const void* data,
|
||||
dword data_length) {
|
||||
dword idi_header_length = ((info & 0xff) == DIVA_STREAM_MESSAGE_TX_IDI_REQUEST && (info & DIVA_STREAMING_IDI_SYSTEM_MESSAGE) == 0) ? (sizeof(diva_spi_msg_hdr_t)+1) : 0;
|
||||
dword length = data_length + idi_header_length + 2 * sizeof(dword); /* data length + message length + info */
|
||||
dword required_length = (length + 31) & ~31;
|
||||
byte tmp[sizeof(dword)+1];
|
||||
byte Req = 0;
|
||||
|
||||
if (required_length > get_free (ifc)) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
WRITE_DWORD(tmp, data_length + idi_header_length + sizeof(dword)); /* Write message length without length dword */
|
||||
write_buffer (ifc, tmp, sizeof(dword));
|
||||
|
||||
if ((info & DIVA_STREAMING_IDI_SYSTEM_MESSAGE) == 0) {
|
||||
switch (info & 0xff) {
|
||||
case DIVA_STREAM_MESSAGE_TX_IDI_REQUEST: {
|
||||
dword ack_info = (word)ifc->ack_rx;
|
||||
Req = (byte)(info >> 8);
|
||||
info = DIVA_STREAMING_IDI_TX_REQUEST | (ack_info << 8);
|
||||
ifc->ack_rx -= ack_info;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_DWORD(tmp, info);
|
||||
write_buffer (ifc, tmp, sizeof(dword)); /* Write info */
|
||||
|
||||
if (idi_header_length != 0) {
|
||||
diva_spi_msg_hdr_t* hdr = (diva_spi_msg_hdr_t*)tmp;
|
||||
dword message_length = data_length + idi_header_length;
|
||||
byte* message_data = (byte*)&hdr[1];
|
||||
|
||||
hdr->Id = 0;
|
||||
hdr->Ind = Req;
|
||||
hdr->length_lo = (byte)message_length;
|
||||
hdr->length_hi = (byte)(message_length >> 8);
|
||||
message_data[0] = 0;
|
||||
|
||||
write_buffer (ifc, hdr, idi_header_length);
|
||||
}
|
||||
|
||||
write_buffer (ifc, data, data_length); /* Write data */
|
||||
|
||||
align_write_buffer (ifc, required_length - length); /* Move to next message */
|
||||
|
||||
return (data_length);
|
||||
}
|
||||
|
||||
static int ack_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length) {
|
||||
if (length > get_in_use (ifc)) {
|
||||
DBG_ERR(("ack error ack:%u in use:%u free:%u [%s]", length, get_in_use (ifc), ifc->state.free_length, ifc->trace_ident))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ifc->state.free_length += length;
|
||||
ifc->state.used_length -= length;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int ack_rx_data (struct _diva_streaming_idi_host_ifc_w* ifc, dword length, int flush_ack) {
|
||||
flush_ack |= (ifc->ack_rx != 0);
|
||||
|
||||
ifc->ack_rx += length;
|
||||
|
||||
while (flush_ack != 0 && ifc->ack_rx != 0 && get_free (ifc) > 128) {
|
||||
dword info = (word)ifc->ack_rx;
|
||||
|
||||
ifc->ack_rx -= info;
|
||||
info = ((dword)DIVA_STREAMING_IDI_RX_ACK_MSG) | (info << 8) | DIVA_STREAMING_IDI_SYSTEM_MESSAGE;
|
||||
|
||||
write_message (ifc, info, 0, 0);
|
||||
update_remote (ifc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static byte description (diva_streaming_idi_host_ifc_w_t* ifc, byte* dst, byte max_length) {
|
||||
byte length = 0;
|
||||
dword i;
|
||||
|
||||
DBG_TRC(("tx description %u segments [%s]", ifc->nr_segments, ifc->trace_ident))
|
||||
|
||||
dst[length++] = (byte)(ifc->nr_segments);
|
||||
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
DBG_TRC((" tx lo[%u] %08x [%s]", i, ifc->segment_lo[i], ifc->trace_ident))
|
||||
WRITE_DWORD(&dst[length], ifc->segment_lo[i]);
|
||||
length += sizeof(dword);
|
||||
}
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
DBG_TRC((" tx hi[%u] %08x [%s]", i, ifc->segment_hi[i], ifc->trace_ident))
|
||||
WRITE_DWORD(&dst[length], ifc->segment_hi[i]);
|
||||
length += sizeof(dword);
|
||||
}
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
DBG_TRC((" length[%u] %u [%s]", i, ifc->segment_length[i], ifc->trace_ident))
|
||||
WRITE_DWORD(&dst[length], ifc->segment_length[i]);
|
||||
length += sizeof(dword);
|
||||
}
|
||||
|
||||
return (length);
|
||||
}
|
||||
|
||||
static int init (struct _diva_streaming_idi_host_ifc_w* ifc, dword version, dword counter, dword info) {
|
||||
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
|
||||
|
||||
if ((info & DIVA_STREAMING_MANAGER_TX_COUNTER_IN_TX_PAGE) != 0) {
|
||||
ifc->segment_length[0] -= sizeof(dword);
|
||||
ifc->state.length -= sizeof(dword);
|
||||
ifc->state.write_buffer_free -= sizeof(dword);
|
||||
ifc->state.free_length -= sizeof(dword);
|
||||
ifc->remote_counter_mapped = (dword*)(ifc->segments[0]+ifc->segment_length[0]);
|
||||
ifc->remote_counter_mapped_base = 0;
|
||||
} else {
|
||||
ifc->remote_counter_offset = counter % (4*1024);
|
||||
ifc->remote_counter_base = counter - ifc->remote_counter_offset;
|
||||
|
||||
ifc->remote_counter_mapped_base = segment_alloc_access->map_address (ifc->segment_alloc,
|
||||
ifc->remote_counter_base, 0,
|
||||
(info & DIVA_STREAMING_MANAGER_HOST_USER_MODE_STREAM) != 0);
|
||||
if (ifc->remote_counter_mapped_base != 0) {
|
||||
byte* p = ifc->remote_counter_mapped_base;
|
||||
ifc->remote_counter_mapped = (dword*)&p[ifc->remote_counter_offset];
|
||||
} else {
|
||||
DBG_TRC(("stream uses system call [%s]", ifc->trace_ident))
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t sync_req (struct _diva_streaming_idi_host_ifc_w* ifc, dword ident) {
|
||||
if (get_free (ifc) > 128) {
|
||||
dword data[2];
|
||||
|
||||
DBG_TRC(("sync request %08x [%s]", ident, ifc->trace_ident))
|
||||
|
||||
data[0] = ident;
|
||||
data[1] = 0;
|
||||
|
||||
write_message (ifc, DIVA_STREAMING_IDI_SYNC_REQ|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
|
||||
update_remote (ifc);
|
||||
|
||||
return (DivaStreamingIdiResultOK);
|
||||
} else {
|
||||
return (DivaStreamingIdiResultBusy);
|
||||
}
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t set_trace_ident (struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
if (get_free (ifc) > 128) {
|
||||
dword data[2];
|
||||
DBG_TRC(("set trace ident [%s]", ifc->trace_ident))
|
||||
|
||||
memcpy (data, ifc->trace_ident, sizeof(data[0]));
|
||||
data[1] = 0;
|
||||
|
||||
write_message (ifc, DIVA_STREAMING_IDI_SET_DEBUG_IDENT|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
|
||||
update_remote (ifc);
|
||||
|
||||
return (DivaStreamingIdiResultOK);
|
||||
} else {
|
||||
return (DivaStreamingIdiResultBusy);
|
||||
}
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t release_stream (struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
dword data[1];
|
||||
int ret;
|
||||
|
||||
DBG_LOG(("stream release [%s]", ifc->trace_ident))
|
||||
|
||||
data[0] = 0;
|
||||
|
||||
ret = write_message (ifc, DIVA_STREAMING_IDI_RELEASE|DIVA_STREAMING_IDI_SYSTEM_MESSAGE, data, sizeof(data));
|
||||
update_remote (ifc);
|
||||
|
||||
return (ret != 0 ? DivaStreamingIdiResultOK : DivaStreamingIdiResultBusy);
|
||||
}
|
||||
|
||||
static int write_data (struct _diva_streaming_idi_host_ifc_w* ifc, const void* data, dword data_length) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int write_indirect (struct _diva_streaming_idi_host_ifc_w* ifc, dword lo, dword hi, dword length) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int update_remote (struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
int ret = 0;
|
||||
|
||||
if (ifc->remote_counter_mapped != 0) {
|
||||
ifc->remote_counter_mapped[0] = ifc->remote.written;
|
||||
} else {
|
||||
diva_segment_alloc_access_t* segment_alloc_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
|
||||
|
||||
ret = segment_alloc_access->write_address (ifc->segment_alloc,
|
||||
ifc->remote_counter_base + ifc->remote_counter_offset,
|
||||
0,
|
||||
ifc->remote.written);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static dword get_in_use (const struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
return (ifc->state.used_length);
|
||||
}
|
||||
|
||||
static dword get_free (const struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
return (ifc->state.free_length);
|
||||
}
|
||||
|
||||
static dword get_length (const struct _diva_streaming_idi_host_ifc_w* ifc) {
|
||||
return (ifc->state.length);
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_IDI_HOST_IFC_IMPL_H__
|
||||
#define __DIVA_STREAMING_IDI_HOST_IFC_IMPL_H__
|
||||
|
||||
struct _diva_segment_alloc_ifc;
|
||||
struct _diva_streaming_idi_host_ifc_w_access;
|
||||
struct _diva_streaming_idi_host_ifc_w;
|
||||
|
||||
#define DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS 8
|
||||
typedef struct _diva_streaming_idi_host_ifc_w {
|
||||
struct _diva_streaming_idi_host_ifc_w_access access;
|
||||
|
||||
byte* segments[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS]; /**< buffer segments */
|
||||
dword segment_length[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS]; /**< length of every segment */
|
||||
dword segment_lo[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS];
|
||||
dword segment_hi[DIVA_STREAMING_IDI_HOST_IFC_MAX_SEGMENTS];
|
||||
dword nr_segments; /**< number of available segments */
|
||||
|
||||
struct _diva_segment_alloc* segment_alloc;
|
||||
|
||||
struct {
|
||||
dword length; /**< overall length including all segments */
|
||||
dword used_length; /**< overall written and not acknowledged */
|
||||
dword free_length; /**< overall length available */
|
||||
|
||||
dword write_buffer; /**< current write segment buffer */
|
||||
dword write_buffer_position; /**< position in write segment */
|
||||
dword write_buffer_free; /**< free space in write segment */
|
||||
|
||||
dword acknowledge_buffer; /**< acknowledge segment */
|
||||
dword acknowledge_buffer_position; /**< position in acknowledge segment */
|
||||
dword acknowledge_buffer_free;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
int32 written; /**< incremented every time data written by amount of data written in the buffer and
|
||||
written to opposite side */
|
||||
} remote;
|
||||
|
||||
dword remote_counter_base; /* Remote counter page BUS address */
|
||||
dword remote_counter_offset; /* Remote counter offset from page start */
|
||||
void* remote_counter_mapped_base; /* Remote counter page BUS address mapped */
|
||||
volatile dword* remote_counter_mapped; /* Remote counter mapped */
|
||||
|
||||
dword ack_rx;
|
||||
|
||||
int free_ifc;
|
||||
|
||||
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
|
||||
} diva_streaming_idi_host_ifc_w_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* vim:ts=2:
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "pc.h"
|
||||
#include "diva_streaming_vector.h"
|
||||
#include "diva_streaming_messages.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_streaming_manager.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_segment_alloc_ifc.h"
|
||||
#include "diva_streaming_idi_host_ifc.h"
|
||||
#include "diva_streaming_idi_host_rx_ifc_impl.h"
|
||||
|
||||
/*
|
||||
* LOCALS
|
||||
*/
|
||||
static void update_buffer (struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
static void align_buffer (struct _diva_streaming_idi_host_ifc_r* ifc, dword length, diva_streaming_vector_t* v, dword* nr_v);
|
||||
static int diva_streaming_idi_host_rx_data (struct _diva_streaming_idi_host_ifc_r* ifc, dword length);
|
||||
static dword copy_message_data (byte* dst, const diva_streaming_vector_t* v, dword nr_v);
|
||||
static int diva_streaming_idi_host_rx_process_message (struct _diva_streaming_idi_host_ifc_r* ifc,
|
||||
dword message,
|
||||
dword data_length,
|
||||
const diva_streaming_vector_t* v, dword nr_v);
|
||||
static byte description (diva_streaming_idi_host_ifc_r_t* ifc, byte* dst, byte max_length);
|
||||
static int diva_streaming_idi_host_rx_ifc_rx (struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
static int diva_streaming_idi_host_rx_ifc_cleanup (struct _diva_streaming_idi_host_ifc_r* ifc);
|
||||
|
||||
int diva_streaming_idi_host_rx_ifc_create (struct _diva_streaming_idi_host_ifc_r** ifc,
|
||||
dword number_segments,
|
||||
struct _diva_segment_alloc* segment_alloc,
|
||||
struct _diva_streaming_idi_host_ifc_w* tx,
|
||||
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc,
|
||||
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc,
|
||||
void* user_context,
|
||||
struct _diva_stream* diva_streaming_manager_ifc,
|
||||
const char* trace_ident) {
|
||||
struct _diva_streaming_idi_host_ifc_r* ifc_r = *ifc;
|
||||
diva_segment_alloc_access_t* segment_access = diva_get_segment_alloc_ifc (segment_alloc);
|
||||
dword i;
|
||||
int free_ifc = 0;
|
||||
|
||||
if (ifc_r == 0) {
|
||||
ifc_r = diva_os_malloc (0, sizeof(*ifc_r));
|
||||
free_ifc = 1;
|
||||
}
|
||||
|
||||
if (ifc_r == 0) {
|
||||
DBG_ERR(("failed to create idi r interface [%s]", trace_ident))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memset (ifc_r, 0x00, sizeof(*ifc_r));
|
||||
memcpy(ifc_r->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
|
||||
ifc_r->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
|
||||
|
||||
ifc_r->nr_segments = MIN(number_segments, DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS);
|
||||
ifc_r->segment_alloc = segment_alloc;
|
||||
ifc_r->free_ifc = free_ifc;
|
||||
ifc_r->diva_streaming_manager_ifc = diva_streaming_manager_ifc;
|
||||
|
||||
for (i = 0; i < ifc_r->nr_segments; i++) {
|
||||
ifc_r->segments[i] = (*(segment_access->segment_alloc))(segment_alloc,
|
||||
&ifc_r->segment_lo[i],
|
||||
&ifc_r->segment_hi[i]);
|
||||
if (ifc_r->segments[i] == 0) {
|
||||
DBG_ERR(("failed to alloc segment [%s]", trace_ident))
|
||||
diva_streaming_idi_host_rx_ifc_cleanup (ifc_r);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
DBG_TRC(("alloc %p %08x:%08x [%s]", ifc_r->segments[i], ifc_r->segment_lo[i], ifc_r->segment_hi[i], trace_ident))
|
||||
|
||||
ifc_r->segment_length[i] = (*(segment_access->get_segment_length))(segment_alloc);
|
||||
|
||||
if (i == 0) {
|
||||
ifc_r->remote_counter = (int32*)ifc_r->segments[i];
|
||||
ifc_r->segments[i] += sizeof(dword);
|
||||
ifc_r->segment_length[i] -= sizeof(dword);
|
||||
}
|
||||
|
||||
ifc_r->state.length += ifc_r->segment_length[i];
|
||||
}
|
||||
|
||||
ifc_r->remote_counter[0] = 0;
|
||||
|
||||
ifc_r->tx = tx;
|
||||
ifc_r->tx_ifc = tx_ifc;
|
||||
ifc_r->notify_user_proc = notify_user_proc;
|
||||
ifc_r->user_context = user_context;
|
||||
|
||||
ifc_r->current_segment = 0;
|
||||
ifc_r->current_pos = 0;
|
||||
ifc_r->current_free = ifc_r->segment_length[ifc_r->current_segment];
|
||||
|
||||
ifc_r->access.release = diva_streaming_idi_host_rx_ifc_cleanup;
|
||||
ifc_r->access.wakeup = diva_streaming_idi_host_rx_ifc_rx;
|
||||
ifc_r->access.description = description;
|
||||
|
||||
*ifc = ifc_r;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct _diva_streaming_idi_host_ifc_r_access* diva_streaming_idi_host_rx_ifc_get_access (
|
||||
struct _diva_streaming_idi_host_ifc_r* ifc) {
|
||||
return (&ifc->access);
|
||||
}
|
||||
|
||||
static int diva_streaming_idi_host_rx_ifc_cleanup (struct _diva_streaming_idi_host_ifc_r* ifc) {
|
||||
diva_segment_alloc_access_t* segment_access = diva_get_segment_alloc_ifc (ifc->segment_alloc);
|
||||
dword i;
|
||||
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
if (ifc->segments[i] != 0) {
|
||||
(*(segment_access->segment_free))(ifc->segment_alloc,
|
||||
ifc->segments[i] - ((i == 0) ? sizeof(dword) : 0),
|
||||
ifc->segment_lo[i],
|
||||
ifc->segment_hi[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifc->free_ifc != 0) {
|
||||
diva_os_free (0, ifc);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive data
|
||||
*/
|
||||
static int diva_streaming_idi_host_rx_ifc_rx (struct _diva_streaming_idi_host_ifc_r* ifc) {
|
||||
int32 local_counter;
|
||||
int32 length;
|
||||
int ret = 0;
|
||||
int msg_count = 0, ack_ret;
|
||||
|
||||
do {
|
||||
local_counter = ifc->remote_counter[0];
|
||||
length = local_counter - ifc->local_counter;
|
||||
|
||||
if (length != 0) {
|
||||
ret += length;
|
||||
ifc->local_counter = local_counter;
|
||||
ack_ret = diva_streaming_idi_host_rx_data (ifc, length);
|
||||
if (ifc->released == DIVA_STREAM_MESSAGE_RELEASE_ACK || ifc->released == DIVA_STREAM_MESSAGE_INIT_ERROR) {
|
||||
if (ifc->notify_user_proc (ifc->user_context, ((dword)ifc->released) << 8 | 0xffU, ifc->released_info, 0, 0) == 0) {
|
||||
ifc->diva_streaming_manager_ifc->release(ifc->diva_streaming_manager_ifc);
|
||||
} else {
|
||||
ifc->released = DIVA_STREAM_MESSAGE_RELEASED;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
ifc->tx_ifc->ack_rx (ifc->tx, length, msg_count != 0 || ack_ret == 0);
|
||||
msg_count++;
|
||||
}
|
||||
} while(length != 0);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void update_buffer (struct _diva_streaming_idi_host_ifc_r* ifc) {
|
||||
if (ifc->current_free == 0) {
|
||||
ifc->current_segment++;
|
||||
if (ifc->current_segment >= ifc->nr_segments) {
|
||||
ifc->current_segment = 0;
|
||||
}
|
||||
ifc->current_free = ifc->segment_length[ifc->current_segment];
|
||||
ifc->current_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void align_buffer (struct _diva_streaming_idi_host_ifc_r* ifc, dword length, diva_streaming_vector_t* v, dword* nr_v) {
|
||||
while (length != 0) {
|
||||
dword to_copy = MIN(ifc->current_free, length);
|
||||
|
||||
if (v != 0) {
|
||||
v[*nr_v].data = ifc->segments[ifc->current_segment] + ifc->current_pos;
|
||||
v[*nr_v].length = to_copy;
|
||||
nr_v[0]++;
|
||||
}
|
||||
|
||||
ifc->current_pos += to_copy;
|
||||
ifc->current_free -= to_copy;
|
||||
length -= to_copy;
|
||||
update_buffer (ifc);
|
||||
}
|
||||
}
|
||||
|
||||
static dword copy_message_data (byte* dst, const diva_streaming_vector_t* v, dword nr_v) {
|
||||
dword i, length;
|
||||
|
||||
for (i = 0, length = 0; i < nr_v; i++) {
|
||||
memcpy (&dst[length], v[i].data, v[i].length);
|
||||
length += v[i].length;
|
||||
}
|
||||
|
||||
return (length);
|
||||
}
|
||||
|
||||
/*
|
||||
Return one if processed DIVA_STREAMING_IDI_TX_ACK_MSG
|
||||
*/
|
||||
static int diva_streaming_idi_host_rx_process_message (struct _diva_streaming_idi_host_ifc_r* ifc,
|
||||
dword message,
|
||||
dword data_length,
|
||||
const diva_streaming_vector_t* v, dword nr_v) {
|
||||
int ret = 0;
|
||||
|
||||
switch (message) {
|
||||
case DIVA_STREAMING_IDI_TX_INIT_MSG: /* Initialization */
|
||||
if (data_length != (DIVA_STREAMING_IDI_TX_INIT_MSG_LENGTH - sizeof(dword) - sizeof(word))) {
|
||||
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_INIT_MSG, data_length, ifc->trace_ident))
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
dword counter;
|
||||
dword info;
|
||||
byte version;
|
||||
|
||||
copy_message_data (ifc->system_message, v, nr_v);
|
||||
|
||||
version = ifc->system_message[0];
|
||||
counter = READ_DWORD(&ifc->system_message[1]);
|
||||
info = READ_DWORD(&ifc->system_message[5]);
|
||||
|
||||
DBG_TRC(("version:%u counter:%08x info:%08x [%s]", version, counter, info, ifc->trace_ident))
|
||||
|
||||
ifc->tx_ifc->init (ifc->tx, version, counter, info);
|
||||
ifc->tx_ifc->trace_ident (ifc->tx);
|
||||
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_INIT << 8 | 0xffU, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DIVA_STREAMING_IDI_TX_ACK_MSG:
|
||||
if (data_length < (DIVA_STREAMING_IDI_TX_ACK_MSG_LENGTH - sizeof(dword) - sizeof(word))) {
|
||||
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_ACK_MSG, data_length, ifc->trace_ident))
|
||||
return (0);
|
||||
}
|
||||
copy_message_data (ifc->system_message, v, nr_v);
|
||||
DBG_TRC(("Ind:%02x %u seq:%u [%s]",
|
||||
DIVA_STREAMING_IDI_TX_ACK_MSG,
|
||||
((word)ifc->system_message[0]) | (((word)ifc->system_message[1]) << 8),
|
||||
ifc->system_message[2],
|
||||
ifc->trace_ident))
|
||||
ifc->tx_ifc->ack (ifc->tx, ((word)ifc->system_message[0]) | (((word)ifc->system_message[1]) << 8));
|
||||
ret = 1;
|
||||
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_RX_TX_ACK << 8 | 0xffU, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case DIVA_STREAMING_IDI_TX_SYNC_ACK:
|
||||
if (data_length != (DIVA_STREAMING_IDI_TX_SYNC_ACK_LENGTH - sizeof(dword) - sizeof(word))) {
|
||||
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_SYNC_ACK, data_length, ifc->trace_ident))
|
||||
return (0);
|
||||
}
|
||||
copy_message_data (ifc->system_message, v, nr_v);
|
||||
{
|
||||
dword ident = READ_DWORD(&ifc->system_message[0]);
|
||||
DBG_TRC(("sync ack %08x [%s]", ident, ifc->trace_ident))
|
||||
|
||||
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_SYNC_ACK << 8 | 0xffU, ident, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DIVA_STREAMING_IDI_RELEASE_ACK:
|
||||
if (data_length != (DIVA_STREAMING_IDI_RELEASE_ACK_LENGTH - sizeof(dword) - sizeof(word))) {
|
||||
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_RELEASE_ACK, data_length, ifc->trace_ident))
|
||||
return (0);
|
||||
}
|
||||
DBG_LOG(("stream release ack [%s]", ifc->trace_ident))
|
||||
ifc->released = DIVA_STREAM_MESSAGE_RELEASE_ACK;
|
||||
ifc->released_info = 0;
|
||||
break;
|
||||
|
||||
case DIVA_STREAMING_IDI_TX_INIT_ERROR:
|
||||
if (data_length < DIVA_STREAMING_IDI_TX_INIT_ERROR_LENGTH - sizeof(dword) - sizeof(word) || data_length >= sizeof(ifc->system_message)) {
|
||||
DBG_ERR(("wrong message length %02x %u [%s]", DIVA_STREAMING_IDI_TX_INIT_ERROR, data_length, ifc->trace_ident))
|
||||
}
|
||||
copy_message_data (ifc->system_message, v, nr_v);
|
||||
{
|
||||
dword error = READ_DWORD(&ifc->system_message[0]);
|
||||
DBG_LOG(("stream init error %08x [%s]", error, ifc->trace_ident))
|
||||
ifc->released = DIVA_STREAM_MESSAGE_INIT_ERROR;
|
||||
ifc->released_info = error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG_ERR(("unknown message %08x %u [%s]", message, data_length, ifc->trace_ident))
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
Return one of only one system ack tx message was processed
|
||||
*/
|
||||
static int diva_streaming_idi_host_rx_data (struct _diva_streaming_idi_host_ifc_r* ifc, dword length) {
|
||||
diva_streaming_vector_t v[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS+2];
|
||||
dword nr_v;
|
||||
int msg_count = 0, ack_msg = 0;
|
||||
|
||||
|
||||
while (length != 0) {
|
||||
dword hdr = *(dword*)(ifc->segments[ifc->current_segment] + ifc->current_pos);
|
||||
dword data_length_lo = hdr & 0xffU;
|
||||
dword data_length_hi = (hdr >> 8) & 0xffU;
|
||||
dword data_length = data_length_lo | (data_length_hi << 8);
|
||||
dword message_length = ((data_length + (sizeof(dword)-1)) & ~(sizeof(dword)-1));
|
||||
dword message_type = (hdr >> 16) & 0xff;
|
||||
dword message = (hdr >> 24) & 0xff;
|
||||
|
||||
length -= (message_length + sizeof(dword)-1) & ~(sizeof(dword)-1);
|
||||
|
||||
nr_v = 0;
|
||||
if (message_type != 0xff && (message & 0x0f) == 0x0f) {
|
||||
/*
|
||||
Tx ack sent as part of IDI N_COMBI_IND message
|
||||
*/
|
||||
byte tmp[sizeof(dword)+sizeof(word)];
|
||||
dword tx_ack;
|
||||
|
||||
align_buffer (ifc, sizeof(dword)+sizeof(word), v, &nr_v); /* Header */
|
||||
copy_message_data (tmp, v, nr_v);
|
||||
tx_ack = ((dword)tmp[4]) | (((dword)tmp[5]) << 8);
|
||||
|
||||
if (tx_ack != 0) {
|
||||
ifc->tx_ifc->ack (ifc->tx, tx_ack);
|
||||
ifc->notify_user_proc (ifc->user_context, DIVA_STREAM_MESSAGE_RX_TX_ACK << 8 | 0xffU, 0, 0, 0);
|
||||
}
|
||||
|
||||
nr_v = 0;
|
||||
} else {
|
||||
align_buffer (ifc, sizeof(dword)+sizeof(word), 0, 0); /* Header */
|
||||
}
|
||||
align_buffer (ifc, data_length - sizeof(dword) - sizeof(word), v, &nr_v);
|
||||
|
||||
if (message_type == 0xff) {
|
||||
ack_msg |= diva_streaming_idi_host_rx_process_message (ifc, message, data_length - sizeof(dword) - sizeof(word), v, nr_v);
|
||||
if (ifc->released != 0)
|
||||
return (1);
|
||||
} else if (nr_v != 0) {
|
||||
ifc->notify_user_proc (ifc->user_context, message << 8, data_length - sizeof(dword) - sizeof(word), v, nr_v);
|
||||
}
|
||||
align_buffer (ifc, message_length - data_length, 0, 0);
|
||||
msg_count++;
|
||||
}
|
||||
|
||||
return (msg_count == 1 && ack_msg != 0);
|
||||
}
|
||||
|
||||
static byte description (diva_streaming_idi_host_ifc_r_t* ifc, byte* dst, byte max_length) {
|
||||
byte length = 0;
|
||||
dword i;
|
||||
|
||||
DBG_TRC(("rx description %u segments [%s]", ifc->nr_segments, ifc->trace_ident))
|
||||
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
DBG_TRC((" rx lo[%u] %08x [%s]", i, ifc->segment_lo[i], ifc->trace_ident))
|
||||
WRITE_DWORD(&dst[length], ifc->segment_lo[i]);
|
||||
length += sizeof(dword);
|
||||
}
|
||||
for (i = 0; i < ifc->nr_segments; i++) {
|
||||
DBG_TRC((" rx hi[%u] %08x [%s]", i, ifc->segment_hi[i], ifc->trace_ident))
|
||||
WRITE_DWORD(&dst[length], ifc->segment_hi[i]);
|
||||
length += sizeof(dword);
|
||||
}
|
||||
|
||||
return (length);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_IDI_HOST_RX_IFC_IMPL_H__
|
||||
#define __DIVA_STREAMING_IDI_HOST_RX_IFC_IMPL_H__
|
||||
|
||||
|
||||
struct _diva_segment_alloc_ifc;
|
||||
struct _diva_streaming_idi_host_ifc_r_access;
|
||||
struct _diva_streaming_idi_host_ifc_r;
|
||||
|
||||
|
||||
#define DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS 8
|
||||
typedef struct _diva_streaming_idi_host_ifc_r {
|
||||
struct _diva_streaming_idi_host_ifc_r_access access;
|
||||
|
||||
byte* segments[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS]; /**< buffer segments */
|
||||
dword segment_length[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS]; /**< length of every segment */
|
||||
dword segment_lo[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS];
|
||||
dword segment_hi[DIVA_STREAMING_IDI_HOST_RX_IFC_MAX_SEGMENTS];
|
||||
dword nr_segments; /**< number of available segments */
|
||||
|
||||
volatile int32* remote_counter; /**< updated by remote side, located at begin of first segment */
|
||||
volatile int32 local_counter;
|
||||
|
||||
dword current_segment;
|
||||
dword current_pos;
|
||||
dword current_free;
|
||||
|
||||
struct _diva_segment_alloc* segment_alloc;
|
||||
|
||||
struct _diva_streaming_idi_host_ifc_w* tx;
|
||||
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc;
|
||||
diva_streaming_idi_rx_notify_user_proc_t notify_user_proc;
|
||||
void* user_context;
|
||||
|
||||
byte system_message[512];
|
||||
|
||||
int free_ifc;
|
||||
|
||||
struct {
|
||||
dword length; /**< overall length including all segments */
|
||||
} state;
|
||||
|
||||
struct _diva_stream* diva_streaming_manager_ifc;
|
||||
dword released;
|
||||
dword released_info;
|
||||
|
||||
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
|
||||
} diva_streaming_idi_host_ifc_r_t;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "pc.h"
|
||||
#include "diva_streaming_result.h"
|
||||
#include "diva_streaming_vector.h"
|
||||
#include "diva_streaming_manager.h"
|
||||
#include "diva_streaming_messages.h"
|
||||
#include "diva_segment_alloc_ifc.h"
|
||||
#include "diva_streaming_idi_host_ifc.h"
|
||||
|
||||
|
||||
typedef struct _diva_stream_manager {
|
||||
diva_stream_t ifc;
|
||||
int user_segment_alloc;
|
||||
struct _diva_segment_alloc* segment_alloc;
|
||||
diva_segment_alloc_access_t* segment_alloc_ifc;
|
||||
struct _diva_streaming_idi_host_ifc_w* tx;
|
||||
struct _diva_streaming_idi_host_ifc_w_access* tx_ifc;
|
||||
struct _diva_streaming_idi_host_ifc_r* rx;
|
||||
struct _diva_streaming_idi_host_ifc_r_access* rx_ifc;
|
||||
diva_streaming_idi_rx_notify_user_proc_t rx_proc;
|
||||
void* rx_proc_context;
|
||||
|
||||
byte description[0xff-32];
|
||||
|
||||
char trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH+1];
|
||||
} diva_stream_manager_t;
|
||||
|
||||
/*
|
||||
* LOCALS
|
||||
*/
|
||||
static int message_input_proc (void* user_context, dword message, dword length, const diva_streaming_vector_t* v, dword nr_v);
|
||||
static diva_streaming_idi_result_t diva_stream_manager_release (struct _diva_stream* ifc);
|
||||
static diva_streaming_idi_result_t diva_stream_manager_release_stream (struct _diva_stream* ifc);
|
||||
static diva_streaming_idi_result_t diva_stream_manager_write (struct _diva_stream* ifc, dword message, const void* data, dword length);
|
||||
static diva_streaming_idi_result_t diva_stream_manager_wakeup (struct _diva_stream* ifc);
|
||||
static const byte* diva_stream_manager_description (struct _diva_stream* ifc, const byte* addie, byte addielen);
|
||||
static diva_streaming_idi_result_t diva_stream_manager_sync_req (struct _diva_stream* ifc, dword ident);
|
||||
static diva_streaming_idi_result_t diva_stream_flush (struct _diva_stream* ifc);
|
||||
static dword diva_stream_get_tx_free (const struct _diva_stream* ifc);
|
||||
static dword diva_stream_get_tx_in_use (const struct _diva_stream* ifc);
|
||||
static void diva_notify_os_resource_removed (struct _diva_stream* ifc);
|
||||
|
||||
diva_streaming_idi_result_t diva_stream_create (struct _diva_stream** ifc,
|
||||
void* os_context,
|
||||
dword length,
|
||||
diva_streaming_idi_rx_notify_user_proc_t rx,
|
||||
void* rx_context,
|
||||
const char* trace_ident) {
|
||||
return (diva_stream_create_with_user_segment_alloc (ifc, os_context, length, rx, rx_context, trace_ident, 0));
|
||||
}
|
||||
|
||||
diva_streaming_idi_result_t diva_stream_create_with_user_segment_alloc (struct _diva_stream** ifc,
|
||||
void* os_context,
|
||||
dword length,
|
||||
diva_streaming_idi_rx_notify_user_proc_t rx,
|
||||
void* rx_context,
|
||||
const char* trace_ident,
|
||||
struct _diva_segment_alloc* user_segment_alloc) {
|
||||
diva_stream_manager_t* pI;
|
||||
diva_streaming_idi_result_t ret = DivaStreamingIdiResultError;
|
||||
|
||||
#ifdef DIVA_USERMODE
|
||||
dbg_init ("DIVA STREAM", "109-1", 0);
|
||||
#endif
|
||||
|
||||
pI = diva_os_malloc (0, sizeof(*pI));
|
||||
|
||||
if (pI != 0) {
|
||||
memset (pI, 0x00, sizeof(*pI));
|
||||
memcpy(pI->trace_ident, trace_ident, MIN(strlen(trace_ident), DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH));
|
||||
pI->trace_ident[DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH] = 0;
|
||||
|
||||
if (user_segment_alloc != 0) {
|
||||
pI->segment_alloc = user_segment_alloc;
|
||||
pI->user_segment_alloc = 1;
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = diva_create_segment_alloc (os_context, &pI->segment_alloc);
|
||||
pI->user_segment_alloc = 0;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
dword number_segments = length/4096 + ((length%4096) != 0);
|
||||
|
||||
pI->segment_alloc_ifc = diva_get_segment_alloc_ifc (pI->segment_alloc);
|
||||
|
||||
ret = diva_streaming_idi_host_ifc_create (&pI->tx, number_segments, pI->segment_alloc, trace_ident);
|
||||
if (ret == 0) {
|
||||
pI->tx_ifc = diva_streaming_idi_host_ifc_get_access (pI->tx);
|
||||
|
||||
ret = diva_streaming_idi_host_rx_ifc_create (&pI->rx, number_segments, pI->segment_alloc, pI->tx, pI->tx_ifc, message_input_proc, pI, &pI->ifc, trace_ident);
|
||||
if (ret == 0) {
|
||||
pI->rx_ifc = diva_streaming_idi_host_rx_ifc_get_access (pI->rx);
|
||||
|
||||
pI->ifc.release = diva_stream_manager_release;
|
||||
pI->ifc.release_stream = diva_stream_manager_release_stream;
|
||||
pI->ifc.write = diva_stream_manager_write;
|
||||
pI->ifc.wakeup = diva_stream_manager_wakeup;
|
||||
pI->ifc.description = diva_stream_manager_description;
|
||||
pI->ifc.sync = diva_stream_manager_sync_req;
|
||||
pI->ifc.flush_stream = diva_stream_flush;
|
||||
pI->ifc.get_tx_free = diva_stream_get_tx_free;
|
||||
pI->ifc.get_tx_in_use = diva_stream_get_tx_in_use;
|
||||
pI->ifc.notify_os_resource_removed = diva_notify_os_resource_removed;
|
||||
|
||||
pI->rx_proc = rx;
|
||||
pI->rx_proc_context = rx_context;
|
||||
|
||||
*ifc = &pI->ifc;
|
||||
ret = DivaStreamingIdiResultOK;
|
||||
} else {
|
||||
DBG_ERR(("failed to create rx stream [%s]", trace_ident))
|
||||
}
|
||||
} else {
|
||||
DBG_ERR(("failed to create tx stream [%s]", trace_ident))
|
||||
}
|
||||
} else {
|
||||
DBG_ERR(("failed to create segment alloc [%s]", trace_ident))
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
diva_stream_manager_release (&pI->ifc);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int message_input_proc (void* user_context, dword message, dword length, const diva_streaming_vector_t* v, dword nr_v) {
|
||||
diva_stream_manager_t* pI = (diva_stream_manager_t*)user_context;
|
||||
|
||||
return (pI->rx_proc (pI->rx_proc_context, message, length, v, nr_v));
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_manager_release (struct _diva_stream* ifc) {
|
||||
if (ifc != 0) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
if (pI->rx != 0)
|
||||
pI->rx_ifc->release (pI->rx);
|
||||
if (pI->tx != 0)
|
||||
pI->tx_ifc->release (pI->tx);
|
||||
if (pI->segment_alloc != 0 && pI->user_segment_alloc == 0)
|
||||
pI->segment_alloc_ifc->release (&pI->segment_alloc);
|
||||
diva_os_free (0, pI);
|
||||
}
|
||||
|
||||
return (DivaStreamingIdiResultOK);
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_manager_release_stream (struct _diva_stream* ifc) {
|
||||
if (ifc != 0) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->release_stream (pI->tx));
|
||||
}
|
||||
|
||||
return (DivaStreamingIdiResultError);
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_manager_write (struct _diva_stream* ifc, dword message, const void* data, dword length) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->write_message (pI->tx, message, data, length));
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_manager_wakeup (struct _diva_stream* ifc) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->rx_ifc->wakeup (pI->rx));
|
||||
}
|
||||
|
||||
const byte* diva_stream_manager_description (struct _diva_stream* ifc, const byte* addie, byte addielen) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
byte length = 4, len_tx, len_rx;
|
||||
|
||||
len_tx = pI->tx_ifc->description (pI->tx, &pI->description[length], sizeof(pI->description)-length);
|
||||
|
||||
if (len_tx != 0) {
|
||||
length += len_tx;
|
||||
len_rx = pI->rx_ifc->description (pI->rx, &pI->description[length], sizeof(pI->description)-length);
|
||||
if (len_rx != 0) {
|
||||
length += len_rx;
|
||||
pI->description[0] = length-1; /* Structure length */
|
||||
pI->description[1] = 0; /* Request */
|
||||
pI->description[2] = len_rx+len_tx+1; /* Structure length */
|
||||
pI->description[3] = 0; /* Version */
|
||||
|
||||
if (addie != 0 && addielen != 0) {
|
||||
byte* description = &pI->description[0];
|
||||
byte* start = &description[3];
|
||||
|
||||
start[0] |= 2U;
|
||||
start = start + start[-1];
|
||||
memcpy (start, addie, addielen);
|
||||
start += addielen;
|
||||
*start++ = 0;
|
||||
|
||||
description[2] += addielen+1;
|
||||
description[0] += addielen+1;
|
||||
length += addielen+1;
|
||||
}
|
||||
|
||||
DBG_TRC(("description length %u [%s]", length, pI->trace_ident))
|
||||
DBG_BLK(((void*)pI->description, length))
|
||||
|
||||
return (&pI->description[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_manager_sync_req (struct _diva_stream* ifc, dword ident) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->sync (pI->tx, ident));
|
||||
}
|
||||
|
||||
static diva_streaming_idi_result_t diva_stream_flush (struct _diva_stream* ifc) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->update_remote (pI->tx) == 0 ? DivaStreamingIdiResultOK : DivaStreamingIdiResultError);
|
||||
}
|
||||
|
||||
static dword diva_stream_get_tx_free (const struct _diva_stream* ifc) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->get_free (pI->tx));
|
||||
}
|
||||
|
||||
static dword diva_stream_get_tx_in_use (const struct _diva_stream* ifc) {
|
||||
const diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, const diva_stream_manager_t, ifc);
|
||||
|
||||
return (pI->tx_ifc->get_in_use (pI->tx));
|
||||
}
|
||||
|
||||
static void diva_notify_os_resource_removed (struct _diva_stream* ifc) {
|
||||
diva_stream_manager_t* pI = DIVAS_CONTAINING_RECORD(ifc, diva_stream_manager_t, ifc);
|
||||
|
||||
if (pI->segment_alloc != 0) {
|
||||
pI->segment_alloc_ifc->resource_removed (pI->segment_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
dword diva_streaming_read_vector_data (const diva_streaming_vector_t* v, int nr_v, dword *vector_offset, dword *vector_position, byte* dst, dword length) {
|
||||
dword to_copy;
|
||||
dword count;
|
||||
|
||||
for (count = 0; vector_offset[0] < ((dword)nr_v) && length != 0;) {
|
||||
to_copy = MIN((v[vector_offset[0]].length - vector_position[0]), length);
|
||||
if (dst != 0) {
|
||||
const byte* tmp = v[vector_offset[0]].data;
|
||||
memcpy (dst, &tmp[vector_position[0]], to_copy);
|
||||
dst += to_copy;
|
||||
}
|
||||
length -= to_copy;
|
||||
count += to_copy;
|
||||
if (v[vector_offset[0]].length == vector_position[0]+to_copy) {
|
||||
vector_offset[0]++;
|
||||
vector_position[0]=0;
|
||||
} else {
|
||||
vector_position[0] += to_copy;
|
||||
}
|
||||
}
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
|
||||
dword diva_streaming_get_indication_data (dword handle, dword message, dword length, const diva_streaming_vector_t* v, int nr_v, byte* pInd, diva_streaming_vector_t* vind, int *pvind_nr) {
|
||||
dword vector_offset = (byte)handle;
|
||||
dword vector_position = handle >> 8;
|
||||
byte Ind = (byte)(message >> 8);
|
||||
byte header[4];
|
||||
dword indication_data_length;
|
||||
int dst_nr_v = *pvind_nr;
|
||||
int i;
|
||||
|
||||
if ((Ind & 0x0f) == 8 /* N_DATA */) {
|
||||
*pInd = Ind;
|
||||
for (i = 0; i < nr_v; i++) {
|
||||
vind[i] = v[i];
|
||||
}
|
||||
*pvind_nr = nr_v;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
Combined indication
|
||||
data[0] = Ind;
|
||||
data[1] = IndCh;
|
||||
data[2] = (byte)length;
|
||||
data[3] = (byte)(length >> 8);
|
||||
*/
|
||||
if (vector_offset >= ((dword)nr_v) || vector_position >= v[vector_offset].length) {
|
||||
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
|
||||
*pInd = 0;
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
const byte* tmp = v[vector_offset].data;
|
||||
if (tmp[vector_position] == 0) {
|
||||
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
|
||||
*pInd = 0;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (diva_streaming_read_vector_data (v, nr_v, &vector_offset, &vector_position, header, sizeof(header)) != sizeof(header)) {
|
||||
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
|
||||
*pInd = 0;
|
||||
return (0);
|
||||
}
|
||||
indication_data_length = ((word)header[2] | (word)header[3] << 8);
|
||||
|
||||
for (i = 0; i < dst_nr_v && indication_data_length != 0; i++) {
|
||||
const byte* tmp = v[vector_offset].data;
|
||||
vind[i].data = &tmp[vector_position];
|
||||
vind[i].length = MIN((v[vector_offset].length - vector_position), indication_data_length);
|
||||
*pvind_nr = i + 1;
|
||||
|
||||
indication_data_length -= vind[i].length;
|
||||
|
||||
if (diva_streaming_read_vector_data (v, nr_v, &vector_offset, &vector_position, 0, vind[i].length) != vind[i].length) {
|
||||
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
|
||||
*pInd = 0;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (indication_data_length != 0) {
|
||||
DBG_ERR(("%s at %d wrong combined indication format", __FILE__, __LINE__))
|
||||
*pInd = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
*pInd = header[0];
|
||||
|
||||
{
|
||||
const byte* tmp = v[vector_offset].data;
|
||||
if (tmp[vector_position] == 0) {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (vector_offset | (vector_position << 8));
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_MANAGER_H__
|
||||
#define __DIVA_STREAMING_MANAGER_H__
|
||||
|
||||
struct _diva_streaming_vector;
|
||||
struct _diva_segment_alloc;
|
||||
|
||||
typedef struct _diva_stream {
|
||||
diva_streaming_idi_result_t (*release)(struct _diva_stream* ifc); /**< destroy stream */
|
||||
diva_streaming_idi_result_t (*release_stream)(struct _diva_stream* ifc); /**< destroy stream */
|
||||
diva_streaming_idi_result_t (*write)(struct _diva_stream* ifc, dword message, const void* data, dword length); /**< write data to stream */
|
||||
diva_streaming_idi_result_t (*wakeup)(struct _diva_stream* ifc);
|
||||
const byte* (*description)(struct _diva_stream* ifc, const byte* addie, byte addielength);
|
||||
diva_streaming_idi_result_t (*sync)(struct _diva_stream* ifc, dword ident);
|
||||
diva_streaming_idi_result_t (*flush_stream)(struct _diva_stream* ifc);
|
||||
dword (*get_tx_free)(const struct _diva_stream* ifc);
|
||||
dword (*get_tx_in_use)(const struct _diva_stream* ifc);
|
||||
void (*notify_os_resource_removed)(struct _diva_stream* ifc);
|
||||
} diva_stream_t;
|
||||
|
||||
/*
|
||||
Message field length one byte
|
||||
*/
|
||||
#define DIVA_STREAM_MESSAGE_TX_DATA 0x00000000 /** Tx data */
|
||||
#define DIVA_STREAM_MESSAGE_TX_DATA_ACK 0x00000001 /** Tx data with ack */
|
||||
#define DIVA_STREAM_MESSAGE_TX_IDI_REQUEST 0x00000002 /** Tx IDI request, request is passed in bits 8...15 */
|
||||
|
||||
#define DIVA_STREAM_MESSAGE_RX_DATA 0x00000000 /** Received data */
|
||||
#define DIVA_STREAM_MESSAGE_RX_TX_FREE 0x00000001 /** Tx space available */
|
||||
#define DIVA_STREAM_MESSAGE_RX_TX_ACK 0x00000002 /** Received Tx Ack message */
|
||||
#define DIVA_STREAM_MESSAGE_INIT 0x00000003 /** Stream init complete */
|
||||
#define DIVA_STREAM_MESSAGE_SYNC_ACK 0x00000004 /** Received stream sync ack */
|
||||
#define DIVA_STREAM_MESSAGE_RELEASE_ACK 0x00000005 /** Received stream release acknowledge */
|
||||
#define DIVA_STREAM_MESSAGE_INIT_ERROR 0x00000007 /** Stream init error */
|
||||
#define DIVA_STREAM_MESSAGE_RELEASED 0x00000008 /** Not message, used internally */
|
||||
|
||||
#define DIVA_STREAMING_MANAGER_HOST_USER_MODE_STREAM 0x40000000U
|
||||
#define DIVA_STREAMING_MANAGER_TX_COUNTER_IN_TX_PAGE 0x20000000U /* Tx counter is located at end of TX page */
|
||||
|
||||
diva_streaming_idi_result_t diva_stream_create_with_user_segment_alloc (struct _diva_stream** ifc,
|
||||
void* os_context,
|
||||
dword length,
|
||||
diva_streaming_idi_rx_notify_user_proc_t rx,
|
||||
void* rx_context,
|
||||
const char* trace_ident,
|
||||
struct _diva_segment_alloc* user_segment_alloc);
|
||||
diva_streaming_idi_result_t diva_stream_create (struct _diva_stream** ifc,
|
||||
void* os_context,
|
||||
dword length,
|
||||
diva_streaming_idi_rx_notify_user_proc_t rx,
|
||||
void* rx_context,
|
||||
const char* trace_ident);
|
||||
|
||||
dword diva_streaming_read_vector_data (const diva_streaming_vector_t* v, int nr_v, dword *vector_offset, dword *vector_position, byte* dst, dword length);
|
||||
dword diva_streaming_get_indication_data (dword handle, dword message, dword length, const diva_streaming_vector_t* v, int nr_v, byte* pInd, diva_streaming_vector_t* vind, int *pvind_nr);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "pc.h"
|
||||
#include "diva_streaming_messages.h"
|
||||
|
||||
int diva_streaming_idi_supported_ind (byte idiInd, dword length, const byte* data) {
|
||||
byte Ind = idiInd & 0x0f;
|
||||
|
||||
if (likely(Ind == N_DATA))
|
||||
return (1);
|
||||
|
||||
if (Ind == N_UDATA && length != 0) {
|
||||
switch (*data) {
|
||||
case UDATA_INDICATION_DTMF_DIGITS_SENT:
|
||||
case UDATA_INDICATION_DTMF_DIGITS_RECEIVED:
|
||||
case UDATA_INDICATION_MIXER_TAP_DATA:
|
||||
case UDATA_INDICATION_RTCP_PACKET:
|
||||
case UDATA_INDICATION_RTCP_GENERATED:
|
||||
case UDATA_INDICATION_RTCP_ACCEPTED:
|
||||
case UDATA_INDICATION_FEC_PACKET:
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int diva_streaming_idi_supported_req (byte idiReq, dword length, const byte* data) {
|
||||
byte Req = idiReq & 0x0f;
|
||||
|
||||
if (likely(Req == N_DATA))
|
||||
return (1);
|
||||
|
||||
if (Req == N_UDATA && length != 0) {
|
||||
switch (*data) {
|
||||
case UDATA_REQUEST_SEND_DTMF_DIGITS:
|
||||
case UDATA_REQUEST_MIXER_TAP_DATA:
|
||||
case UDATA_REQUEST_RTCP_PACKET:
|
||||
case UDATA_REQUEST_RTCP_GENERATE:
|
||||
case UDATA_REQUEST_RTCP_ACCEPT:
|
||||
case UDATA_REQUEST_FEC_PACKET:
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_MESSAGES_H__
|
||||
#define __DIVA_STREAMING_MESSAGES_H__
|
||||
|
||||
/*
|
||||
* Tx direction (to IDI)
|
||||
*/
|
||||
#define DIVA_STREAMING_IDI_SYSTEM_MESSAGE 0x80000000U
|
||||
#define DIVA_STREAMING_IDI_RX_ACK_MSG 0x02 /* Ack processed by host data */
|
||||
#define DIVA_STREAMING_IDI_SYNC_REQ 0x03 /* Sync request */
|
||||
#define DIVA_STREAMING_IDI_RELEASE 0x04 /* Release stream */
|
||||
#define DIVA_STREAMING_IDI_SET_DEBUG_IDENT 0x05 /* Set debug ident */
|
||||
#define DIVA_STREAMING_IDI_TX_REQUEST 0x07
|
||||
|
||||
|
||||
/*
|
||||
* Rx direction (to host)
|
||||
*/
|
||||
#define DIVA_STREAMING_IDI_TX_INIT_MSG 0x01 /* Init message, created version, counter address */
|
||||
#define DIVA_STREAMING_IDI_TX_INIT_MSG_LENGTH 15
|
||||
#define DIVA_STREAMING_IDI_TX_ACK_MSG 0x02 /* Ack processed by tx data */
|
||||
#define DIVA_STREAMING_IDI_TX_ACK_MSG_LENGTH 0x09
|
||||
#define DIVA_STREAMING_IDI_TX_SYNC_ACK 0x03 /* Sync request acknowledge */
|
||||
#define DIVA_STREAMING_IDI_TX_SYNC_ACK_LENGTH 0x0a
|
||||
#define DIVA_STREAMING_IDI_RELEASE_ACK 0x04
|
||||
#define DIVA_STREAMING_IDI_RELEASE_ACK_LENGTH 0x08
|
||||
#define DIVA_STREAMING_IDI_TX_INIT_ERROR 0x05
|
||||
#define DIVA_STREAMING_IDI_TX_INIT_ERROR_LENGTH 0x0a
|
||||
|
||||
|
||||
#ifndef UDATA_REQUEST_SEND_DTMF_DIGITS
|
||||
#define UDATA_REQUEST_SEND_DTMF_DIGITS 16
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_DTMF_DIGITS_SENT
|
||||
#define UDATA_INDICATION_DTMF_DIGITS_SENT 16
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_DTMF_DIGITS_RECEIVED
|
||||
#define UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17
|
||||
#endif
|
||||
|
||||
#ifndef UDATA_REQUEST_MIXER_TAP_DATA
|
||||
#define UDATA_REQUEST_MIXER_TAP_DATA 27
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_MIXER_TAP_DATA
|
||||
#define UDATA_INDICATION_MIXER_TAP_DATA 27
|
||||
#endif
|
||||
|
||||
#ifndef UDATA_REQUEST_RTCP_PACKET
|
||||
#define UDATA_REQUEST_RTCP_PACKET 67
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_RTCP_PACKET
|
||||
#define UDATA_INDICATION_RTCP_PACKET 67
|
||||
#endif
|
||||
|
||||
#ifndef UDATA_REQUEST_RTCP_GENERATE
|
||||
#define UDATA_REQUEST_RTCP_GENERATE 68
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_RTCP_GENERATED
|
||||
#define UDATA_INDICATION_RTCP_GENERATED 68
|
||||
#endif
|
||||
#ifndef UDATA_REQUEST_RTCP_ACCEPT
|
||||
#define UDATA_REQUEST_RTCP_ACCEPT 69
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_RTCP_ACCEPTED
|
||||
#define UDATA_INDICATION_RTCP_ACCEPTED 69
|
||||
#endif
|
||||
|
||||
#ifndef UDATA_REQUEST_FEC_PACKET
|
||||
#define UDATA_REQUEST_FEC_PACKET 70
|
||||
#endif
|
||||
#ifndef UDATA_INDICATION_FEC_PACKET
|
||||
#define UDATA_INDICATION_FEC_PACKET 70
|
||||
#endif
|
||||
|
||||
int diva_streaming_idi_supported_ind (byte idiInd, dword length, const byte* data);
|
||||
int diva_streaming_idi_supported_req (byte idiReq, dword length, const byte* data);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_RESULT_H__
|
||||
#define __DIVA_STREAMING_RESULT_H__
|
||||
|
||||
typedef enum {
|
||||
DivaStreamingIdiResultOK = 0,
|
||||
DivaStreamingIdiResultError = -1,
|
||||
DivaStreamingIdiResultBusy = -2
|
||||
} diva_streaming_idi_result_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_STREAMING_VECTOR_H__
|
||||
#define __DIVA_STREAMING_VECTOR_H__
|
||||
|
||||
typedef struct _diva_streaming_vector {
|
||||
const void* data;
|
||||
dword length;
|
||||
} diva_streaming_vector_t;
|
||||
|
||||
typedef int (*diva_streaming_idi_rx_notify_user_proc_t)(void* user_context, dword message, dword length, const struct _diva_streaming_vector* v, dword nr_v);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,932 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef PC_H_INCLUDED /* { */
|
||||
#define PC_H_INCLUDED
|
||||
/*------------------------------------------------------------------*/
|
||||
/* buffer definition */
|
||||
/*------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
word length; /* length of data/parameter field */
|
||||
byte P[270]; /* data/parameter field */
|
||||
} PBUFFER;
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dual port ram structure */
|
||||
/*------------------------------------------------------------------*/
|
||||
struct dual
|
||||
{
|
||||
byte Req; /* request register */
|
||||
byte ReqId; /* request task/entity identification */
|
||||
byte Rc; /* return code register */
|
||||
byte RcId; /* return code task/entity identification */
|
||||
byte Ind; /* Indication register */
|
||||
byte IndId; /* Indication task/entity identification */
|
||||
byte IMask; /* Interrupt Mask Flag */
|
||||
byte RNR; /* Receiver Not Ready (set by PC) */
|
||||
byte XLock; /* XBuffer locked Flag */
|
||||
byte Int; /* ISDN-S interrupt */
|
||||
byte ReqCh; /* Channel field for layer-3 Requests */
|
||||
byte RcCh; /* Channel field for layer-3 Returncodes */
|
||||
byte IndCh; /* Channel field for layer-3 Indications */
|
||||
byte MInd; /* more data indication field */
|
||||
word MLength; /* more data total packet length */
|
||||
byte ReadyInt; /* request field for ready interrupt */
|
||||
byte SWReg; /* Software register for special purposes */
|
||||
byte Reserved[11]; /* reserved space */
|
||||
byte InterfaceType; /* interface type 1=16K interface */
|
||||
word Signature; /* ISDN-S adapter Signature (GD) */
|
||||
PBUFFER XBuffer; /* Transmit Buffer */
|
||||
PBUFFER RBuffer; /* Receive Buffer */
|
||||
};
|
||||
/*------------------------------------------------------------------*/
|
||||
/* SWReg Values (0 means no command) */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define SWREG_DIE_WITH_LEDON 0x01
|
||||
#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Id Fields Coding */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define IDI_ID_MASK 0xe0 /* Mask for the ID field */
|
||||
#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
|
||||
#define DSIG_ID 0x00 /* ID for D-channel signaling */
|
||||
#define NL_ID 0x20 /* ID for network-layer access (B or D) */
|
||||
#define BLLC_ID 0x60 /* ID for B-channel link level access */
|
||||
#define TASK_ID 0x80 /* ID for dynamic user tasks */
|
||||
#define TIMER_ID 0xa0 /* ID for timer task */
|
||||
#define TEL_ID 0xc0 /* ID for telephone support */
|
||||
#define MAN_ID 0xe0 /* ID for management */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* ASSIGN and REMOVE requests are the same for all entities */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define ASSIGN 0x01
|
||||
#define UREMOVE 0xfe /* without return code */
|
||||
#define REMOVE 0xff
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Timer Interrupt Task Interface */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define ASSIGN_TIM 0x01
|
||||
#define REMOVE_TIM 0xff
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dynamic user task interface */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define ASSIGN_TSK 0x01
|
||||
#define REMOVE_TSK 0xff
|
||||
#define LOAD 0xf0
|
||||
#define RELOCATE 0xf1
|
||||
#define START 0xf2
|
||||
#define LOAD2 0xf3
|
||||
#define RELOCATE2 0xf4
|
||||
/*------------------------------------------------------------------*/
|
||||
/* dynamic user task messages */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define TSK_B2 0x0000
|
||||
#define TSK_WAKEUP 0x2000
|
||||
#define TSK_TIMER 0x4000
|
||||
#define TSK_TSK 0x6000
|
||||
#define TSK_PC 0xe000
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LL management primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define ASSIGN_LL 1 /* assign logical link */
|
||||
#define REMOVE_LL 0xff /* remove logical link */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* LL service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define LL_UDATA 1 /* link unit data request/indication */
|
||||
#define LL_ESTABLISH 2 /* link establish request/indication */
|
||||
#define LL_RELEASE 3 /* link release request/indication */
|
||||
#define LL_DATA 4 /* data request/indication */
|
||||
#define LL_LOCAL 5 /* switch to local operation (COM only) */
|
||||
#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
|
||||
#define LL_REMOTE 6 /* switch to remote operation (COM only) */
|
||||
#define LL_TEST 8 /* link test request */
|
||||
#define LL_MDATA 9 /* more data request/indication */
|
||||
#define LL_BUDATA 10 /* broadcast unit data request/indication */
|
||||
#define LL_XID 12 /* XID command request/indication */
|
||||
#define LL_XID_R 13 /* XID response request/indication */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* NL service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define N_MDATA 1 /* more data to come REQ/IND */
|
||||
#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
|
||||
#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
|
||||
#define N_DISC 4 /* OSI N-DISC REQ/IND */
|
||||
#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
|
||||
#define N_RESET 6 /* OSI N-RESET REQ/IND */
|
||||
#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
|
||||
#define N_DATA 8 /* OSI N-DATA REQ/IND */
|
||||
#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
|
||||
#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
|
||||
#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
|
||||
#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
|
||||
#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
|
||||
#define N_XON 15 /* clear RNR state */
|
||||
#define N_COMBI_IND N_XON /* combined indication */
|
||||
#define N_Q_BIT 0x10 /* Q-bit for req/ind */
|
||||
#define N_M_BIT 0x20 /* M-bit for req/ind */
|
||||
#define N_D_BIT 0x40 /* D-bit for req/ind */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Signaling management primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define ASSIGN_SIG 1 /* assign signaling task */
|
||||
#define UREMOVE_SIG 0xfe /* remove signaling task without return code*/
|
||||
#define REMOVE_SIG 0xff /* remove signaling task */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Signaling service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define CALL_REQ 1 /* call request */
|
||||
#define CALL_CON 1 /* call confirmation */
|
||||
#define CALL_IND 2 /* incoming call connected */
|
||||
#define LISTEN_REQ 2 /* listen request */
|
||||
#define HANGUP 3 /* hangup request/indication */
|
||||
#define SUSPEND 4 /* call suspend request/confirm */
|
||||
#define RESUME 5 /* call resume request/confirm */
|
||||
#define SUSPEND_REJ 6 /* suspend rejected indication */
|
||||
#define USER_DATA 8 /* user data for user to user signaling */
|
||||
#define CONGESTION 9 /* network congestion indication */
|
||||
#define INDICATE_REQ 10 /* request to indicate an incoming call */
|
||||
#define INDICATE_IND 10 /* indicates that there is an incoming call */
|
||||
#define CALL_RES 11 /* accept an incoming call */
|
||||
#define CALL_ALERT 12 /* send ALERT for incoming call */
|
||||
#define INFO_REQ 13 /* INFO request */
|
||||
#define INFO_IND 13 /* INFO indication */
|
||||
#define REJECT 14 /* reject an incoming call */
|
||||
#define RESOURCES 15 /* reserve B-Channel hardware resources */
|
||||
#define HW_CTRL 16 /* B-Channel hardware IOCTL req/ind */
|
||||
#define TEL_CTRL 16 /* Telephone control request/indication */
|
||||
#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */
|
||||
#define FAC_REG_REQ 18 /* 1TR6 connection independent fac reg */
|
||||
#define FAC_REG_ACK 19 /* 1TR6 fac registration acknowledge */
|
||||
#define FAC_REG_REJ 20 /* 1TR6 fac registration reject */
|
||||
#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */
|
||||
#define SW_CTRL 22 /* extended software features */
|
||||
#define REGISTER_REQ 23 /* Q.931 connection independent reg req */
|
||||
#define REGISTER_IND 24 /* Q.931 connection independent reg ind */
|
||||
#define FACILITY_REQ 25 /* Q.931 connection independent fac req */
|
||||
#define FACILITY_IND 26 /* Q.931 connection independent fac ind */
|
||||
#define NCR_INFO_REQ 27 /* INFO_REQ with NULL CR */
|
||||
#define GCR_MIM_REQ 28 /* MANAGEMENT_INFO_REQ with global CR */
|
||||
#define SIG_CTRL 29 /* Control for Signalling Hardware */
|
||||
#define DSP_CTRL 30 /* Control for DSPs */
|
||||
#define LAW_REQ 31 /* Law config request for (returns info_i) */
|
||||
#define SPID_CTRL 32 /* Request/indication SPID related */
|
||||
#define NCR_FACILITY 33 /* Request/indication with NULL/DUMMY CR */
|
||||
#define CALL_HOLD 34 /* Request/indication to hold a CALL */
|
||||
#define CALL_RETRIEVE 35 /* Request/indication to retrieve a CALL */
|
||||
#define CALL_HOLD_ACK 36 /* OK of hold a CALL */
|
||||
#define CALL_RETRIEVE_ACK 37 /* OK of retrieve a CALL */
|
||||
#define CALL_HOLD_REJ 38 /* Reject of hold a CALL */
|
||||
#define CALL_RETRIEVE_REJ 39 /* Reject of retrieve a call */
|
||||
#define GCR_RESTART 40 /* Send/Receive Restart message */
|
||||
#define S_SERVICE 41 /* Send/Receive Supplementary Service */
|
||||
#define S_SERVICE_REJ 42 /* Reject Supplementary Service indication */
|
||||
#define S_SUPPORTED 43 /* Req/Ind to get Supported Services */
|
||||
#define STATUS_ENQ 44 /* Req to send the D-ch request if !state0 */
|
||||
#define CALL_GUARD 45 /* Req/Ind to use the FLAGS_CALL_OUTCHECK */
|
||||
#define CALL_GUARD_HP 46 /* Call Guard function to reject a call */
|
||||
#define CALL_GUARD_IF 47 /* Call Guard function, inform the appl */
|
||||
#define SSEXT_REQ 48 /* Supplem.Serv./QSIG specific request */
|
||||
#define SSEXT_IND 49 /* Supplem.Serv./QSIG specific indication */
|
||||
/* reserved commands for the US protocols */
|
||||
#define INT_3PTY_NIND 50 /* US specific indication */
|
||||
#define INT_CF_NIND 51 /* US specific indication */
|
||||
#define INT_3PTY_DROP 52 /* US specific indication */
|
||||
#define INT_MOVE_CONF 53 /* US specific indication */
|
||||
#define INT_MOVE_RC 54 /* US specific indication */
|
||||
#define INT_MOVE_FLIPPED_CONF 55 /* US specific indication */
|
||||
#define INT_X5NI_OK 56 /* internal transfer OK indication */
|
||||
#define INT_XDMS_START 57 /* internal transfer OK indication */
|
||||
#define INT_XDMS_STOP 58 /* internal transfer finish indication */
|
||||
#define INT_XDMS_STOP2 59 /* internal transfer send FA */
|
||||
#define INT_CUSTCONF_REJ 60 /* internal conference reject */
|
||||
#define INT_CUSTXFER 61 /* internal transfer request */
|
||||
#define INT_CUSTX_NIND 62 /* internal transfer ack */
|
||||
#define INT_CUSTXREJ_NIND 63 /* internal transfer rej */
|
||||
#define INT_X5NI_CF_XFER 64 /* internal transfer OK indication */
|
||||
#define VSWITCH_REQ 65 /* communication between protocol and */
|
||||
#define VSWITCH_IND 66 /* capifunctions for D-CH-switching */
|
||||
#define MWI_POLL 67 /* Message Waiting Status Request fkt */
|
||||
#define CALL_PEND_NOTIFY 68 /* notify capi to set new listen */
|
||||
#define DO_NOTHING 69 /* dont do somethin if you get this */
|
||||
#define INT_CT_REJ 70 /* ECT rejected internal command */
|
||||
#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete */
|
||||
#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete */
|
||||
#define RESERVE_REQ 73 /* Request to reserve resources */
|
||||
#define RESERVE_IND 73 /* Indication for granted resources */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* management service primitives */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define MAN_READ 2
|
||||
#define MAN_WRITE 3
|
||||
#define MAN_EXECUTE 4
|
||||
#define MAN_EVENT_ON 5
|
||||
#define MAN_EVENT_OFF 6
|
||||
#define MAN_LOCK 7
|
||||
#define MAN_UNLOCK 8
|
||||
#define MAN_INFO_IND 2
|
||||
#define MAN_EVENT_IND 3
|
||||
#define MAN_TRACE_IND 4
|
||||
#define MAN_COMBI_IND 9
|
||||
#define MAN_ESC 0x80
|
||||
/*------------------------------------------------------------------*/
|
||||
/* return code coding */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define UNKNOWN_COMMAND 0x01 /* unknown command */
|
||||
#define WRONG_COMMAND 0x02 /* wrong command */
|
||||
#define WRONG_ID 0x03 /* unknown task/entity id */
|
||||
#define WRONG_CH 0x04 /* wrong task/entity id */
|
||||
#define UNKNOWN_IE 0x05 /* unknown information el. */
|
||||
#define WRONG_IE 0x06 /* wrong information el. */
|
||||
#define OUT_OF_RESOURCES 0x07 /* ISDN-S card out of res. */
|
||||
#define OUT_OF_LICENSES 0x08 /* ISDN-S card out of res. */
|
||||
#define ISDN_GUARD_REJ 0x09 /* ISDN-Guard SuppServ rej */
|
||||
#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */
|
||||
#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */
|
||||
#define ASSIGN_OK 0xef /* ASSIGN OK */
|
||||
#define OK_FC 0xfc /* Flow-Control RC */
|
||||
#define READY_INT 0xfd /* Ready interrupt */
|
||||
#define TIMER_INT 0xfe /* timer interrupt */
|
||||
#define OK 0xff /* command accepted */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* information elements */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define SHIFT 0x90 /* codeset shift */
|
||||
#define MORE 0xa0 /* more data */
|
||||
#define SDNCMPL 0xa1 /* sending complete */
|
||||
#define CL 0xb0 /* congestion level */
|
||||
/* codeset 0 */
|
||||
#define SMSG 0x00 /* segmented message */
|
||||
#define BC 0x04 /* Bearer Capability */
|
||||
#define CAU 0x08 /* cause */
|
||||
#define CAD 0x0c /* Connected address */
|
||||
#define CAI 0x10 /* call identity */
|
||||
#define CHI 0x18 /* channel identification */
|
||||
#define LLI 0x19 /* logical link id */
|
||||
#define CHA 0x1a /* charge advice */
|
||||
#define FTY 0x1c /* Facility */
|
||||
#define DT 0x29 /* ETSI date/time */
|
||||
#define KEY 0x2c /* keypad information element */
|
||||
#define UID 0x2d /* User id information element */
|
||||
#define DSP 0x28 /* display */
|
||||
#define SIG 0x34 /* signalling hardware control */
|
||||
#define OAD 0x6c /* origination address */
|
||||
#define OSA 0x6d /* origination sub-address */
|
||||
#define CPN 0x70 /* called party number */
|
||||
#define DSA 0x71 /* destination sub-address */
|
||||
#define RDX 0x73 /* redirecting number extended */
|
||||
#define RDN 0x74 /* redirecting number */
|
||||
#define RIN 0x76 /* redirection number */
|
||||
#define IUP 0x76 /* VN6 rerouter->PCS (codeset 6) */
|
||||
#define IPU 0x77 /* VN6 PCS->rerouter (codeset 6) */
|
||||
#define RI 0x79 /* restart indicator */
|
||||
#if defined(MIE)
|
||||
#undef MIE
|
||||
#endif
|
||||
#define MIE 0x7a /* management info element */
|
||||
#define LLC 0x7c /* low layer compatibility */
|
||||
#define HLC 0x7d /* high layer compatibility */
|
||||
#define UUI 0x7e /* user user information */
|
||||
#define ESC 0x7f /* escape extension */
|
||||
#define DLC 0x20 /* data link layer configuration */
|
||||
#define NLC 0x21 /* network layer configuration */
|
||||
#define REDIRECT_IE 0x22 /* redirection request/indication data */
|
||||
#define REDIRECT_NET_IE 0x23 /* redirection network override data */
|
||||
/* codeset 6 */
|
||||
#define SIN 0x01 /* service indicator */
|
||||
#define CIF 0x02 /* charging information */
|
||||
#define DATE 0x03 /* date */
|
||||
#define CPS 0x07 /* called party status */
|
||||
#define OLINE 0x01 /* codeset 6, ANI II used in US networks - e.g. verizon - feature group D */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* ESC information elements */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define MSGTYPEIE 0x7a /* Messagetype info element */
|
||||
#define CRIE 0x7b /* INFO info element */
|
||||
#define CODESET6IE 0xec /* Tunnel for Codeset 6 IEs */
|
||||
#define VSWITCHIE 0xed /* VSwitch info element */
|
||||
#define SSEXTIE 0xee /* Supplem. Service info element */
|
||||
#define PROFILEIE 0xef /* Profile info element */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Extended cause codes */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define GUARD_ERROR 0x05
|
||||
#define L1_ERROR 0x08
|
||||
#define TEI_ERROR 0x09
|
||||
#define L2_ERROR 0x0a
|
||||
#define L3_ERROR 0x0b
|
||||
#define OUT_OF_RESOURCES_ERROR 0x0c
|
||||
#define OUT_OF_LICENSES_ERROR 0x0d
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Supplementary Services Misc Defines */
|
||||
/* some defines that are only used in protocol are defined in q931.h*/
|
||||
/*------------------------------------------------------------------*/
|
||||
#define SSTRANSPORT 0x000d
|
||||
#define HOLD_NOTIFY 0x00
|
||||
#define RETRIEVE_NOTIFY 0x01
|
||||
#define SCS7IE_IND 0x02
|
||||
#define SCNT_IND 0x03
|
||||
#define CARDIDENT_IND 0x04
|
||||
#define LINKIDENT_IND 0x05
|
||||
#define SSTUNNEL 0x000f
|
||||
#define SSIDENTIFIER 0x0010
|
||||
#define CQ_PRIDENT 0x0011
|
||||
#define CQ_PRCALLDETAILS 0x0012
|
||||
/*------------------------------------------------------------------*/
|
||||
/* TEL_CTRL contents */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define RING_ON 0x01
|
||||
#define RING_OFF 0x02
|
||||
#define HANDS_FREE_ON 0x03
|
||||
#define HANDS_FREE_OFF 0x04
|
||||
#define ON_HOOK 0x80
|
||||
#define OFF_HOOK 0x90
|
||||
/* operation values used by ETSI supplementary services */
|
||||
#define THREE_PTY_BEGIN 0x04
|
||||
#define THREE_PTY_END 0x05
|
||||
#define ECT_EXECUTE 0x06
|
||||
#define ACTIVATION_DIVERSION 0x07
|
||||
#define DEACTIVATION_DIVERSION 0x08
|
||||
#define CALL_DEFLECTION 0x0D
|
||||
#define INTERROGATION_DIVERSION 0x0B
|
||||
#define INTERROGATION_SERV_USR_NR 0x11
|
||||
#define ACTIVATION_MWI 0x20
|
||||
#define DEACTIVATION_MWI 0x21
|
||||
#define MWI_INDICATION 0x22
|
||||
#define MWI_RESPONSE 0x23
|
||||
#define CONF_BEGIN 0x28
|
||||
#define CONF_ADD 0x29
|
||||
#define CONF_SPLIT 0x2a
|
||||
#define CONF_DROP 0x2b
|
||||
#define CONF_ISOLATE 0x2c
|
||||
#define CONF_REATTACH 0x2d
|
||||
#define CONF_PARTYDISC 0x2e
|
||||
#define CCBS_INFO_RETAIN 0x2f
|
||||
#define CCBS_ERASECALLLINKAGEID 0x30
|
||||
#define CCBS_STOP_ALERTING 0x31
|
||||
#define CCBS_REQUEST 0x32
|
||||
#define CCBS_DEACTIVATE 0x33
|
||||
#define CCBS_INTERROGATE 0x34
|
||||
#define CCBS_STATUS 0x35
|
||||
#define CCBS_ERASE 0x36
|
||||
#define CCBS_B_FREE 0x37
|
||||
#define CCNR_INFO_RETAIN 0x38
|
||||
#define CCBS_REMOTE_USER_FREE 0x39
|
||||
#define CCNR_REQUEST 0x3a
|
||||
#define CCNR_INTERROGATE 0x3b
|
||||
#define CCBS_IN_SET_CB 0x3c
|
||||
#define CCBS_IN_CLEAR_CB 0x3d
|
||||
#define CCBS_IN_AVAILABLE 0x3e
|
||||
#define GET_SUPPORTED_SERVICES 0xff
|
||||
#define DIVERSION_PROCEDURE_CFU 0x70
|
||||
#define DIVERSION_PROCEDURE_CFB 0x71
|
||||
#define DIVERSION_PROCEDURE_CFNR 0x72
|
||||
#define DIVERSION_DEACTIVATION_CFU 0x80
|
||||
#define DIVERSION_DEACTIVATION_CFB 0x81
|
||||
#define DIVERSION_DEACTIVATION_CFNR 0x82
|
||||
#define DIVERSION_INTERROGATE_NUM 0x11
|
||||
#define DIVERSION_INTERROGATE_CFU 0x60
|
||||
#define DIVERSION_INTERROGATE_CFB 0x61
|
||||
#define DIVERSION_INTERROGATE_CFNR 0x62
|
||||
/* Service Masks */
|
||||
#define SMASK_HOLD_RETRIEVE 0x00000001
|
||||
#define SMASK_TERMINAL_PORTABILITY 0x00000002
|
||||
#define SMASK_ECT 0x00000004
|
||||
#define SMASK_3PTY 0x00000008
|
||||
#define SMASK_CALL_FORWARDING 0x00000010
|
||||
#define SMASK_CALL_DEFLECTION 0x00000020
|
||||
#define SMASK_MCID 0x00000040
|
||||
#define SMASK_CCBS 0x00000080
|
||||
#define SMASK_MWI 0x00000100
|
||||
#define SMASK_CCNR 0x00000200
|
||||
#define SMASK_CONF 0x00000400
|
||||
/* ----------------------------------------------
|
||||
Types of transfers used to transfer the
|
||||
information in the 'struct RC->Reserved2[8]'
|
||||
The information is transferred as 2 dwords
|
||||
(2 4Byte unsigned values)
|
||||
First of them is the transfer type.
|
||||
2^32-1 possible messages are possible in this way.
|
||||
The context of the second one had no meaning
|
||||
---------------------------------------------- */
|
||||
#define DIVA_RC_TYPE_NONE 0x00000000
|
||||
#define DIVA_RC_TYPE_REMOVE_COMPLETE 0x00000008
|
||||
#define DIVA_RC_TYPE_STREAM_PTR 0x00000009
|
||||
#define DIVA_RC_TYPE_CMA_PTR 0x0000000a
|
||||
#define DIVA_RC_TYPE_OK_FC 0x0000000b
|
||||
#define DIVA_RC_TYPE_RX_DMA 0x0000000c
|
||||
/* ------------------------------------------------------
|
||||
IO Control codes for IN BAND SIGNALING
|
||||
------------------------------------------------------ */
|
||||
#define CTRL_L1_SET_SIG_ID 5
|
||||
#define CTRL_L1_SET_DAD 6
|
||||
#define CTRL_L1_RESOURCES 7
|
||||
/* ------------------------------------------------------ */
|
||||
/* ------------------------------------------------------
|
||||
Layer 2 types
|
||||
------------------------------------------------------ */
|
||||
#define X75T 1 /* x.75 for ttx */
|
||||
#define TRF 2 /* transparent with hdlc framing */
|
||||
#define TRF_IN 3 /* transparent with hdlc fr. inc. */
|
||||
#define SDLC 4 /* sdlc, sna layer-2 */
|
||||
#define X75 5 /* x.75 for btx */
|
||||
#define LAPD 6 /* lapd (Q.921) */
|
||||
#define X25_L2 7 /* x.25 layer-2 */
|
||||
#define V120_L2 8 /* V.120 layer-2 protocol */
|
||||
#define V42_IN 9 /* V.42 layer-2 protocol, incomming */
|
||||
#define V42 10 /* V.42 layer-2 protocol */
|
||||
#define MDM_ATP 11 /* AT Parser built in the L2 */
|
||||
#define X75_V42BIS 12 /* x.75 with V.42bis */
|
||||
#define RTPL2_IN 13 /* RTP layer-2 protocol, incomming */
|
||||
#define RTPL2 14 /* RTP layer-2 protocol */
|
||||
#define V120_V42BIS 15 /* V.120 asynchronous mode supporting V.42bis compression */
|
||||
#define T38 16 /* T38 layer-2 protocol */
|
||||
#define T38_IN 17 /* T38 layer-2 protocol */
|
||||
#define LISTENER 27 /* Layer 2 to listen line */
|
||||
#define MTP2 28 /* MTP2 Layer 2 */
|
||||
#define PIAFS_CRC 29 /* PIAFS Layer 2 with CRC calculation at L2 */
|
||||
/* ------------------------------------------------------
|
||||
PIAFS DLC DEFINITIONS
|
||||
------------------------------------------------------ */
|
||||
#define PIAFS_64K 0x01
|
||||
#define PIAFS_VARIABLE_SPEED 0x02
|
||||
#define PIAFS_CHINESE_SPEED 0x04
|
||||
#define PIAFS_UDATA_ABILITY_ID 0x80
|
||||
#define PIAFS_UDATA_ABILITY_DCDON 0x01
|
||||
#define PIAFS_UDATA_ABILITY_DDI 0x80
|
||||
/*
|
||||
DLC of PIAFS :
|
||||
Byte | 8 7 6 5 4 3 2 1
|
||||
-----+--------------------------------------------------------
|
||||
0 | 0 0 1 0 0 0 0 0 Data Link Configuration
|
||||
1 | X X X X X X X X Length of IE (at least 15 Bytes)
|
||||
2 | 0 0 0 0 0 0 0 0 max. information field, LOW byte (not used, fix 73 Bytes)
|
||||
3 | 0 0 0 0 0 0 0 0 max. information field, HIGH byte (not used, fix 73 Bytes)
|
||||
4 | 0 0 0 0 0 0 0 0 address A (not used)
|
||||
5 | 0 0 0 0 0 0 0 0 address B (not used)
|
||||
6 | 0 0 0 0 0 0 0 0 Mode (not used, fix 128)
|
||||
7 | 0 0 0 0 0 0 0 0 Window Size (not used, fix 127)
|
||||
8 | X X X X X X X X XID Length, Low Byte (at least 7 Bytes)
|
||||
9 | X X X X X X X X XID Length, High Byte
|
||||
10 | 0 0 0 0 0 C V S PIAFS Protocol Speed configuration -> Note(1)
|
||||
| S = 0 -> Protocol Speed is 32K
|
||||
| S = 1 -> Protocol Speed is 64K
|
||||
| V = 0 -> Protocol Speed is fixed
|
||||
| V = 1 -> Protocol Speed is variable
|
||||
| C = 0 -> speed setting according to standard
|
||||
| C = 1 -> speed setting for chinese implementation
|
||||
11 | 0 0 0 0 0 0 R T P0 - V42bis Compression enable/disable, Low Byte
|
||||
| T = 0 -> Transmit Direction enable
|
||||
| T = 1 -> Transmit Direction disable
|
||||
| R = 0 -> Receive Direction enable
|
||||
| R = 1 -> Receive Direction disable
|
||||
13 | 0 0 0 0 0 0 0 0 P0 - V42bis Compression enable/disable, High Byte
|
||||
14 | X X X X X X X X P1 - V42bis Dictionary Size, Low Byte
|
||||
15 | X X X X X X X X P1 - V42bis Dictionary Size, High Byte
|
||||
16 | X X X X X X X X P2 - V42bis String Length, Low Byte
|
||||
17 | X X X X X X X X P2 - V42bis String Length, High Byte
|
||||
18 | X X X X X X X X PIAFS extension length
|
||||
19 | 1 0 0 0 0 0 0 0 PIAFS extension Id (0x80) - UDATA abilities
|
||||
20 | U 0 0 0 0 0 0 D UDATA abilities -> Note (2)
|
||||
| up to now the following Bits are defined:
|
||||
| D - signal DCD ON
|
||||
| U - use extensive UDATA control communication
|
||||
| for DDI test application
|
||||
+ Note (1): ----------+------+-----------------------------------------+
|
||||
| PIAFS Protocol | Bit | |
|
||||
| Speed configuration | S | Bit 1 - Protocol Speed |
|
||||
| | | 0 - 32K |
|
||||
| | | 1 - 64K (default) |
|
||||
| | V | Bit 2 - Variable Protocol Speed |
|
||||
| | | 0 - Speed is fix |
|
||||
| | | 1 - Speed is variable (default) |
|
||||
| | | OVERWRITES 32k Bit 1 |
|
||||
| | C | Bit 3 0 - Speed Settings according to |
|
||||
| | | PIAFS specification |
|
||||
| | | 1 - Speed setting for chinese |
|
||||
| | | PIAFS implementation |
|
||||
| | | Explanation for chinese speed settings: |
|
||||
| | | if Bit 3 is set the following |
|
||||
| | | rules apply: |
|
||||
| | | Bit1=0 Bit2=0: 32k fix |
|
||||
| | | Bit1=1 Bit2=0: 64k fix |
|
||||
| | | Bit1=0 Bit2=1: PIAFS is trying |
|
||||
| | | to negotiate 32k is that is |
|
||||
| | | not possible it tries to |
|
||||
| | | negotiate 64k |
|
||||
| | | Bit1=1 Bit2=1: PIAFS is trying |
|
||||
| | | to negotiate 64k is that is |
|
||||
| | | not possible it tries to |
|
||||
| | | negotiate 32k |
|
||||
+ Note (2): ----------+------+-----------------------------------------+
|
||||
| PIAFS | Bit | this byte defines the usage of UDATA |
|
||||
| Implementation | | control communication |
|
||||
| UDATA usage | D | Bit 1 - DCD-ON signalling |
|
||||
| | | 0 - no DCD-ON is signalled |
|
||||
| | | (default) |
|
||||
| | | 1 - DCD-ON will be signalled |
|
||||
| | U | Bit 8 - DDI test application UDATA |
|
||||
| | | control communication |
|
||||
| | | 0 - no UDATA control |
|
||||
| | | communication (default) |
|
||||
| | | sets as well the DCD-ON |
|
||||
| | | signalling |
|
||||
| | | 1 - UDATA control communication |
|
||||
| | | ATTENTION: Do not use these |
|
||||
| | | setting if you |
|
||||
| | | are not really |
|
||||
| | | that you need it |
|
||||
| | | and you know |
|
||||
| | | exactly what you |
|
||||
| | | are doing. |
|
||||
| | | You can easily |
|
||||
| | | disable any |
|
||||
| | | data transfer. |
|
||||
+---------------------+------+-----------------------------------------+
|
||||
*/
|
||||
/* ------------------------------------------------------
|
||||
LISTENER DLC DEFINITIONS
|
||||
------------------------------------------------------ */
|
||||
#define LISTENER_FEATURE_MASK_CUMMULATIVE 0x0001
|
||||
/* ------------------------------------------------------
|
||||
LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
|
||||
------------------------------------------------------ */
|
||||
#define META_CODE_LL_UDATA_RX 0x01
|
||||
#define META_CODE_LL_UDATA_TX 0x02
|
||||
#define META_CODE_LL_DATA_RX 0x03
|
||||
#define META_CODE_LL_DATA_TX 0x04
|
||||
#define META_CODE_LL_MDATA_RX 0x05
|
||||
#define META_CODE_LL_MDATA_TX 0x06
|
||||
#define META_CODE_EMPTY 0x10
|
||||
#define META_CODE_LOST_FRAMES 0x11
|
||||
#define META_FLAG_TRUNCATED 0x0001
|
||||
/*------------------------------------------------------------------*/
|
||||
/* CAPI-like profile to indicate features on LAW_REQ */
|
||||
/* Please note: ANY ADDITIONS/CHANGES MUST be documented in */
|
||||
/* LEODMS://process_docs/hardware/HWInfoStruct.html */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define GL_INTERNAL_CONTROLLER_SUPPORTED 0x00000001L
|
||||
#define GL_EXTERNAL_EQUIPMENT_SUPPORTED 0x00000002L
|
||||
#define GL_HANDSET_SUPPORTED 0x00000004L
|
||||
#define GL_DTMF_SUPPORTED 0x00000008L
|
||||
#define GL_SUPPLEMENTARY_SERVICES_SUPPORTED 0x00000010L
|
||||
#define GL_CHANNEL_ALLOCATION_SUPPORTED 0x00000020L
|
||||
#define GL_BCHANNEL_OPERATION_SUPPORTED 0x00000040L
|
||||
#define GL_LINE_INTERCONNECT_SUPPORTED 0x00000080L
|
||||
#define GL_BROADBAND_EXTENSIONS_SUPPORTED 0x00000100L
|
||||
#define GL_ECHO_CANCELLER_SUPPORTED 0x00000200L
|
||||
#define B1_HDLC_SUPPORTED 0x00000001L
|
||||
#define B1_TRANSPARENT_SUPPORTED 0x00000002L
|
||||
#define B1_V110_ASYNC_SUPPORTED 0x00000004L
|
||||
#define B1_V110_SYNC_SUPPORTED 0x00000008L
|
||||
#define B1_T30_SUPPORTED 0x00000010L
|
||||
#define B1_HDLC_INVERTED_SUPPORTED 0x00000020L
|
||||
#define B1_TRANSPARENT_R_SUPPORTED 0x00000040L
|
||||
#define B1_MODEM_ALL_NEGOTIATE_SUPPORTED 0x00000080L
|
||||
#define B1_MODEM_ASYNC_SUPPORTED 0x00000100L
|
||||
#define B1_MODEM_SYNC_HDLC_SUPPORTED 0x00000200L
|
||||
#define B2_X75_SUPPORTED 0x00000001L
|
||||
#define B2_TRANSPARENT_SUPPORTED 0x00000002L
|
||||
#define B2_SDLC_SUPPORTED 0x00000004L
|
||||
#define B2_LAPD_SUPPORTED 0x00000008L
|
||||
#define B2_T30_SUPPORTED 0x00000010L
|
||||
#define B2_PPP_SUPPORTED 0x00000020L
|
||||
#define B2_TRANSPARENT_NO_CRC_SUPPORTED 0x00000040L
|
||||
#define B2_MODEM_EC_COMPRESSION_SUPPORTED 0x00000080L
|
||||
#define B2_X75_V42BIS_SUPPORTED 0x00000100L
|
||||
#define B2_V120_ASYNC_SUPPORTED 0x00000200L
|
||||
#define B2_V120_ASYNC_V42BIS_SUPPORTED 0x00000400L
|
||||
#define B2_V120_BIT_TRANSPARENT_SUPPORTED 0x00000800L
|
||||
#define B2_LAPD_FREE_SAPI_SEL_SUPPORTED 0x00001000L
|
||||
#define B3_TRANSPARENT_SUPPORTED 0x00000001L
|
||||
#define B3_T90NL_SUPPORTED 0x00000002L
|
||||
#define B3_ISO8208_SUPPORTED 0x00000004L
|
||||
#define B3_X25_DCE_SUPPORTED 0x00000008L
|
||||
#define B3_T30_SUPPORTED 0x00000010L
|
||||
#define B3_T30_WITH_EXTENSIONS_SUPPORTED 0x00000020L
|
||||
#define B3_RESERVED_SUPPORTED 0x00000040L
|
||||
#define B3_MODEM_SUPPORTED 0x00000080L
|
||||
#define MANUFACTURER_FEATURE_SLAVE_CODEC 0x00000001L
|
||||
#define MANUFACTURER_FEATURE_FAX_MORE_DOCUMENTS 0x00000002L
|
||||
#define MANUFACTURER_FEATURE_HARDDTMF 0x00000004L
|
||||
#define MANUFACTURER_FEATURE_SOFTDTMF_SEND 0x00000008L
|
||||
#define MANUFACTURER_FEATURE_DTMF_PARAMETERS 0x00000010L
|
||||
#define MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE 0x00000020L
|
||||
#define MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD 0x00000040L
|
||||
#define MANUFACTURER_FEATURE_V18 0x00000080L
|
||||
#define MANUFACTURER_FEATURE_MIXER_CH_CH 0x00000100L
|
||||
#define MANUFACTURER_FEATURE_MIXER_CH_PC 0x00000200L
|
||||
#define MANUFACTURER_FEATURE_MIXER_PC_CH 0x00000400L
|
||||
#define MANUFACTURER_FEATURE_MIXER_PC_PC 0x00000800L
|
||||
#define MANUFACTURER_FEATURE_ECHO_CANCELLER 0x00001000L
|
||||
#define MANUFACTURER_FEATURE_RTP 0x00002000L
|
||||
#define MANUFACTURER_FEATURE_T38 0x00004000L
|
||||
#define MANUFACTURER_FEATURE_TRANSP_DELIVERY_CONF 0x00008000L
|
||||
#define MANUFACTURER_FEATURE_XONOFF_FLOW_CONTROL 0x00010000L
|
||||
#define MANUFACTURER_FEATURE_OOB_CHANNEL 0x00020000L
|
||||
#define MANUFACTURER_FEATURE_IN_BAND_CHANNEL 0x00040000L
|
||||
#define MANUFACTURER_FEATURE_IN_BAND_FEATURE 0x00080000L
|
||||
#define MANUFACTURER_FEATURE_PIAFS 0x00100000L
|
||||
#define MANUFACTURER_FEATURE_DTMF_TONE 0x00200000L
|
||||
#define MANUFACTURER_FEATURE_FAX_PAPER_FORMATS 0x00400000L
|
||||
#define MANUFACTURER_FEATURE_OK_FC_LABEL 0x00800000L
|
||||
#define MANUFACTURER_FEATURE_VOWN 0x01000000L
|
||||
#define MANUFACTURER_FEATURE_XCONNECT 0x02000000L
|
||||
#define MANUFACTURER_FEATURE_DMACONNECT 0x04000000L
|
||||
#define MANUFACTURER_FEATURE_AUDIO_TAP 0x08000000L
|
||||
#define MANUFACTURER_FEATURE_FAX_NONSTANDARD 0x10000000L
|
||||
#define MANUFACTURER_FEATURE_SS7 0x20000000L
|
||||
#define MANUFACTURER_FEATURE_MADAPTER 0x40000000L
|
||||
#define MANUFACTURER_FEATURE_MEASURE 0x80000000L
|
||||
#define MANUFACTURER_FEATURE2_LISTENING 0x00000001L
|
||||
#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
|
||||
#define MANUFACTURER_FEATURE2_GENERIC_TONE 0x00000004L
|
||||
#define MANUFACTURER_FEATURE2_COLOR_FAX 0x00000008L
|
||||
#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
|
||||
#define MANUFACTURER_FEATURE2_TRANSPARENT_N_RESET 0x00000020L
|
||||
/*
|
||||
Following four bits are reserved for vendor specific extensions
|
||||
Vendor specific extension allows values from 0x01 to 0x0e
|
||||
*/
|
||||
#define MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT 6 /* 0x00000040L */
|
||||
#define MANUFACTURER_FEATURE2_VENDOR_BITS 0x0000000fL
|
||||
#define MANUFACTURER_FEATURE2_VENDOR_MASK \
|
||||
(MANUFACTURER_FEATURE2_VENDOR_BITS << MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT)
|
||||
#define MANUFACTURER_FEATURE2_CAPTARIS_ADAPTER \
|
||||
(0x00000001L << MANUFACTURER_FEATURE2_VENDOR_MASK_FIRST_BIT)
|
||||
#define MANUFACTURER_FEATURE2_DIALING_CHARS_ACCEPTED 0x00000400L
|
||||
#define MANUFACTURER_FEATURE2_NULL_PLCI 0x00000800L
|
||||
#define MANUFACTURER_FEATURE2_X25_REVERSE_RESTART 0x00001000L
|
||||
#define MANUFACTURER_FEATURE2_SOFTIP 0x00002000L
|
||||
#define MANUFACTURER_FEATURE2_CLEAR_CHANNEL 0x00004000L
|
||||
#define MANUFACTURER_FEATURE2_LINE_SIDE_T38 0x00008000L
|
||||
#define MANUFACTURER_FEATURE2_RTP_LINE 0x00010000L
|
||||
#define MANUFACTURER_FEATURE2_NO_CLOCK_LINE 0x00020000L
|
||||
#define MANUFACTURER_FEATURE2_TRANSCODING 0x00040000L
|
||||
#define MANUFACTURER_FEATURE2_MODEM_V34_V90 0x00080000L
|
||||
#define MANUFACTURER_FEATURE2_PLUGIN_MODULATION 0x00100000L
|
||||
#define MANUFACTURER_FEATURE2_FAX_V34 0x00200000L
|
||||
#define MANUFACTURER_FEATURE2_MODEM_V34_LOW 0x00400000L
|
||||
#define MANUFACTURER_FEATURE2_STREAMING_IDI 0x00800000L
|
||||
#define RTP_PRIM_PAYLOAD_PCMU_8000 0
|
||||
#define RTP_PRIM_PAYLOAD_1016_8000 1
|
||||
#define RTP_PRIM_PAYLOAD_LINEAR16_8000 1
|
||||
#define RTP_PRIM_PAYLOAD_G726_32_8000 2
|
||||
#define RTP_PRIM_PAYLOAD_GSM_8000 3
|
||||
#define RTP_PRIM_PAYLOAD_G723_8000 4
|
||||
#define RTP_PRIM_PAYLOAD_DVI4_8000 5
|
||||
#define RTP_PRIM_PAYLOAD_DVI4_16000 6
|
||||
#define RTP_PRIM_PAYLOAD_LPC_8000 7
|
||||
#define RTP_PRIM_PAYLOAD_PCMA_8000 8
|
||||
#define RTP_PRIM_PAYLOAD_G722_16000 9
|
||||
#define RTP_PRIM_PAYLOAD_QCELP_8000 12
|
||||
#define RTP_PRIM_PAYLOAD_G728_8000 14
|
||||
#define RTP_PRIM_PAYLOAD_G729_8000 18
|
||||
#define RTP_PRIM_PAYLOAD_RTAUDIO_8000 26
|
||||
#define RTP_PRIM_PAYLOAD_ILBC_8000 27
|
||||
#define RTP_PRIM_PAYLOAD_AMR_NB_8000 28
|
||||
#define RTP_PRIM_PAYLOAD_T38 29
|
||||
#define RTP_PRIM_PAYLOAD_GSM_HR_8000 30
|
||||
#define RTP_PRIM_PAYLOAD_GSM_EFR_8000 31
|
||||
#define RTP_ADD_PAYLOAD_BASE 32
|
||||
#define RTP_ADD_PAYLOAD_RED 32
|
||||
#define RTP_ADD_PAYLOAD_CN_8000 33
|
||||
#define RTP_ADD_PAYLOAD_DTMF 34
|
||||
#define RTP_ADD_PAYLOAD_FEC 35
|
||||
#define RTP_PRIM_PAYLOAD_PCMU_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMU_8000)
|
||||
#define RTP_PRIM_PAYLOAD_1016_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_1016_8000)
|
||||
#define RTP_PRIM_PAYLOAD_LINEAR16_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_LINEAR16_8000)
|
||||
#define RTP_PRIM_PAYLOAD_G726_32_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G726_32_8000)
|
||||
#define RTP_PRIM_PAYLOAD_GSM_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_8000)
|
||||
#define RTP_PRIM_PAYLOAD_G723_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G723_8000)
|
||||
#define RTP_PRIM_PAYLOAD_DVI4_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_8000)
|
||||
#define RTP_PRIM_PAYLOAD_DVI4_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_DVI4_16000)
|
||||
#define RTP_PRIM_PAYLOAD_LPC_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_LPC_8000)
|
||||
#define RTP_PRIM_PAYLOAD_PCMA_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_PCMA_8000)
|
||||
#define RTP_PRIM_PAYLOAD_G722_16000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G722_16000)
|
||||
#define RTP_PRIM_PAYLOAD_QCELP_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_QCELP_8000)
|
||||
#define RTP_PRIM_PAYLOAD_G728_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G728_8000)
|
||||
#define RTP_PRIM_PAYLOAD_G729_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_G729_8000)
|
||||
#define RTP_PRIM_PAYLOAD_RTAUDIO_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_RTAUDIO_8000)
|
||||
#define RTP_PRIM_PAYLOAD_ILBC_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_ILBC_8000)
|
||||
#define RTP_PRIM_PAYLOAD_AMR_NB_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_AMR_NB_8000)
|
||||
#define RTP_PRIM_PAYLOAD_T38_SUPPORTED (1L << RTP_PRIM_PAYLOAD_T38)
|
||||
#define RTP_PRIM_PAYLOAD_GSM_HR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_HR_8000)
|
||||
#define RTP_PRIM_PAYLOAD_GSM_EFR_8000_SUPPORTED (1L << RTP_PRIM_PAYLOAD_GSM_EFR_8000)
|
||||
#define RTP_ADD_PAYLOAD_RED_SUPPORTED (1L << (RTP_ADD_PAYLOAD_RED - RTP_ADD_PAYLOAD_BASE))
|
||||
#define RTP_ADD_PAYLOAD_CN_8000_SUPPORTED (1L << (RTP_ADD_PAYLOAD_CN_8000 - RTP_ADD_PAYLOAD_BASE))
|
||||
#define RTP_ADD_PAYLOAD_DTMF_SUPPORTED (1L << (RTP_ADD_PAYLOAD_DTMF - RTP_ADD_PAYLOAD_BASE))
|
||||
#define RTP_ADD_PAYLOAD_FEC_SUPPORTED (1L << (RTP_ADD_PAYLOAD_FEC - RTP_ADD_PAYLOAD_BASE))
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Definitions to indicate Layer 1/2/3 status on STATUS_REQ */
|
||||
/*------------------------------------------------------------------*/
|
||||
#define CST_STATE_LAYER_MASK 0xe000
|
||||
#define CST_STATE_UP_BIT 0x1000
|
||||
#define CST_STATE_UP_INSTANCES_MASK 0x0fff
|
||||
#define CST_STATE_PROTOCOL_MASK 0xe03f
|
||||
#define CST_STATE_LEVEL_MASK 0x0fc0
|
||||
#define CST_STATE_LAYER_D_L1 0x0000
|
||||
#define CST_STATE_LAYER_D_L2 0x2000
|
||||
#define CST_STATE_LAYER_D_L3 0x4000
|
||||
#define CST_STATE_LAYER_B_L1 0x8000
|
||||
#define CST_STATE_LAYER_B_L2 0xa000
|
||||
#define CST_STATE_LAYER_B_L3 0xc000
|
||||
#define CST_STATE_I430(level) (CST_STATE_LAYER_D_L1 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_I431(level) (CST_STATE_LAYER_D_L1 | 0x01 | ((level) << 6))
|
||||
#define CST_STATE_Q921(level) (CST_STATE_LAYER_D_L2 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_Q931(level) (CST_STATE_LAYER_D_L3 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_CAS(level) (CST_STATE_LAYER_D_L3 | 0x01 | ((level) << 6))
|
||||
#define CST_STATE_HDLC(level) (CST_STATE_LAYER_B_L1 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_V110(level) (CST_STATE_LAYER_B_L1 | 0x01 | ((level) << 6))
|
||||
#define CST_STATE_X75(level) (CST_STATE_LAYER_B_L2 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_X25(level) (CST_STATE_LAYER_B_L3 | 0x00 | ((level) << 6))
|
||||
#define CST_STATE_I430_INACTIVE (CST_STATE_I430(0x00)) /* ITU-T I.430: F1 */
|
||||
#define CST_STATE_I430_TE_SENSING (CST_STATE_I430(0x04)) /* ITU-T I.430: F2 */
|
||||
#define CST_STATE_I430_TE_SENSING_LOW_POWER (CST_STATE_I430(0x05)) /* ITU-T I.430: F2, low power mode */
|
||||
#define CST_STATE_I430_DEACTIVATED (CST_STATE_I430(0x08)) /* ITU-T I.430: F3/G1 */
|
||||
#define CST_STATE_I430_DEACTIVATED_LOW_POWER (CST_STATE_I430(0x09)) /* ITU-T I.430: F3/G1, low power mode */
|
||||
#define CST_STATE_I430_TE_AWAITING_SIGNAL (CST_STATE_I430(0x10)) /* ITU-T I.430: F4 */
|
||||
#define CST_STATE_I430_NT_PENDING_ACTIVATION (CST_STATE_I430(0x11)) /* ITU-T I.430: G2 */
|
||||
#define CST_STATE_I430_TE_IDENTIFYING_INPUT (CST_STATE_I430(0x20)) /* ITU-T I.430: F5 */
|
||||
#define CST_STATE_I430_TE_SYNCHRONIZED (CST_STATE_I430(0x22)) /* ITU-T I.430: F6 */
|
||||
#define CST_STATE_I430_ACTIVATED (CST_STATE_LAYER_D_L1 | CST_STATE_UP_BIT) /* ITU-T I.430: F7/G3 */
|
||||
#define CST_STATE_I430_NT_PENDING_DEACTIVATION (CST_STATE_I430(0x1f)) /* ITU-T I.430: G4 */
|
||||
#define CST_STATE_I430_TE_LOSS_OF_FRAMING (CST_STATE_I430(0x21)) /* ITU-T I.430: F8 */
|
||||
#define CST_STATE_I431_INACTIVE (CST_STATE_I431(0x00)) /* ITU-T I.431: F0/G0 */
|
||||
#define CST_STATE_I431_OPERATIONAL (CST_STATE_LAYER_D_L1 | CST_STATE_UP_BIT) /* ITU-T I.431: F1/G1 */
|
||||
#define CST_STATE_I431_REMOTE_ALARM (CST_STATE_I431(0x26)) /* ITU-T I.431: F2/G2, FC1, yellow alarm */
|
||||
#define CST_STATE_I431_LOSS_OF_SIGNAL (CST_STATE_I431(0x14)) /* ITU-T I.431: F3/G3, FC2, red alarm */
|
||||
#define CST_STATE_I431_LOSS_OF_FRAMING (CST_STATE_I431(0x24)) /* ITU-T I.431: F4/G4, FC3, blue alarm */
|
||||
#define CST_STATE_I431_REMOTE_ALARM_CRC_ERR (CST_STATE_I431(0x25)) /* ITU-T I.431: F5/G5, FC4, yellow alarm, CRC errors */
|
||||
#define CST_STATE_I431_POWER_ON (CST_STATE_I431(0x01)) /* ITU-T I.431: F6/G6 */
|
||||
#define CST_STATE_I431_LOSS_OF_DOUBLEFRAMING (CST_STATE_I431(0x27)) /* */
|
||||
#define CST_STATE_I431_LOSS_OF_MULTIFRAMING (CST_STATE_I431(0x28)) /* */
|
||||
#define CST_STATE_I431_TS16_LOSS_OF_SIGNAL (CST_STATE_I431(0x2e)) /* All zeroes in timeslot 16 */
|
||||
#define CST_STATE_I431_TS16_REMOTE_ALARM (CST_STATE_I431(0x36)) /* Remote alarm bit RS1.2 set in timeslot 16 */
|
||||
#define CST_STATE_I431_TS16_ALARM_INDICATION (CST_STATE_I431(0x30)) /* Less than 4 zeroes in 2 consecutive multiframes */
|
||||
#define CST_STATE_I431_TS16_LOSS_OF_MULTIFRAMING (CST_STATE_I431(0x38)) /* CAS framing pattern lost */
|
||||
#define CST_STATE_I431_EXCESSIVE_ZEROES_DETECTED (CST_STATE_I431(0x1e)) /* More than 3 (HDB3) or 15 (AMI) consecutive zeroes */
|
||||
#define CST_STATE_I431_TRANSMIT_LINE_SHORT (CST_STATE_I431(0x0d)) /* */
|
||||
#define CST_STATE_I431_TRANSMIT_LINE_OPEN (CST_STATE_I431(0x0e)) /* */
|
||||
#define CST_STATE_Q921_TEI_UNASSIGNED (CST_STATE_Q921(0x00)) /* ITU-T Q.921: 4.3 State 1/B.2 State 1 */
|
||||
#define CST_STATE_Q921_ASSIGN_AWAITING_TEI (CST_STATE_Q921(0x08)) /* ITU-T Q.921: B.2 State 2 */
|
||||
#define CST_STATE_Q921_ESTABLISH_AWAITING_TEI (CST_STATE_Q921(0x09)) /* ITU-T Q.921: B.2 State 3 */
|
||||
#define CST_STATE_Q921_TEI_ASSIGNED (CST_STATE_Q921(0x10)) /* ITU-T Q.921: B.2 State 4 */
|
||||
#define CST_STATE_Q921_AWAITING_ESTABLISHMENT (CST_STATE_Q921(0x20)) /* ITU-T Q.921: 4.3 State 2/B.2 State 5 */
|
||||
#define CST_STATE_Q921_AWAITING_RELEASE (CST_STATE_Q921(0x3f)) /* ITU-T Q.921: 4.3 State 3/B.2 State 6 */
|
||||
#define CST_STATE_Q921_MULTIPLE_FRAME_ESTABLISHED (CST_STATE_LAYER_D_L2 | CST_STATE_UP_BIT) /* ITU-T Q.921: 4.3 State 4/B.2 State 7 */
|
||||
#define CST_STATE_Q921_TIMER_RECOVERY (CST_STATE_Q921(0x21)) /* ITU-T Q.921: B.2 State 8 */
|
||||
#define CST_STATE_Q931_NULL (CST_STATE_Q931(0x00)) /* ITU-T Q.931: U0/N0 */
|
||||
#define CST_STATE_Q931_CALL_INITIATED (CST_STATE_Q931(0x01)) /* ITU-T Q.931: U1/N1 */
|
||||
#define CST_STATE_Q931_OVERLAP_SENDING (CST_STATE_Q931(0x02)) /* ITU-T Q.931: U2/N2 */
|
||||
#define CST_STATE_Q931_OUTGOING_CALL_PROCEEDING (CST_STATE_Q931(0x03)) /* ITU-T Q.931: U3/N3 */
|
||||
#define CST_STATE_Q931_CALL_DELIVERED (CST_STATE_Q931(0x04)) /* ITU-T Q.931: U4/N4 */
|
||||
#define CST_STATE_Q931_CALL_PRESENT (CST_STATE_Q931(0x06)) /* ITU-T Q.931: U6/N6 */
|
||||
#define CST_STATE_Q931_CALL_RECEIVED (CST_STATE_Q931(0x07)) /* ITU-T Q.931: U7/N7 */
|
||||
#define CST_STATE_Q931_CONNECT_REQUEST (CST_STATE_Q931(0x08)) /* ITU-T Q.931: U8/N8 */
|
||||
#define CST_STATE_Q931_INCOMING_CALL_PROCEEDING (CST_STATE_Q931(0x09)) /* ITU-T Q.931: U9/N9 */
|
||||
#define CST_STATE_Q931_ACTIVE (CST_STATE_LAYER_D_L3 | CST_STATE_UP_BIT) /* ITU-T Q.931: U10/N10 */
|
||||
#define CST_STATE_Q931_DISCONNECT_REQUEST (CST_STATE_Q931(0x0b)) /* ITU-T Q.931: U11/N11 */
|
||||
#define CST_STATE_Q931_DISCONNECT_INDICATION (CST_STATE_Q931(0x0c)) /* ITU-T Q.931: U12/N12 */
|
||||
#define CST_STATE_Q931_SUSPEND_REQUEST (CST_STATE_Q931(0x0f)) /* ITU-T Q.931: U15/N15 */
|
||||
#define CST_STATE_Q931_RESUME_REQUEST (CST_STATE_Q931(0x11)) /* ITU-T Q.931: U17/N17 */
|
||||
#define CST_STATE_Q931_RELEASE_REQUEST (CST_STATE_Q931(0x13)) /* ITU-T Q.931: U19/N19 */
|
||||
#define CST_STATE_Q931_CALL_ABORT (CST_STATE_Q931(0x16)) /* ITU-T Q.931: N22 */
|
||||
#define CST_STATE_Q931_OVERLAP_RECEIVING (CST_STATE_Q931(0x19)) /* ITU-T Q.931: U25/N25 */
|
||||
#define CST_STATE_CAS_NULL (CST_STATE_CAS(0x00)) /* like ITU-T Q.931: U0/N0 */
|
||||
#define CST_STATE_CAS_CALL_INITIATED (CST_STATE_CAS(0x01)) /* like ITU-T Q.931: U1/N1 */
|
||||
#define CST_STATE_CAS_OVERLAP_SENDING (CST_STATE_CAS(0x02)) /* like ITU-T Q.931: U2/N2 */
|
||||
#define CST_STATE_CAS_OUTGOING_CALL_PROCEEDING (CST_STATE_CAS(0x03)) /* like ITU-T Q.931: U3/N3 */
|
||||
#define CST_STATE_CAS_CALL_DELIVERED (CST_STATE_CAS(0x04)) /* like ITU-T Q.931: U4/N4 */
|
||||
#define CST_STATE_CAS_CALL_PRESENT (CST_STATE_CAS(0x06)) /* like ITU-T Q.931: U6/N6 */
|
||||
#define CST_STATE_CAS_CALL_RECEIVED (CST_STATE_CAS(0x07)) /* like ITU-T Q.931: U7/N7 */
|
||||
#define CST_STATE_CAS_CONNECT_REQUEST (CST_STATE_CAS(0x08)) /* like ITU-T Q.931: U8/N8 */
|
||||
#define CST_STATE_CAS_INCOMING_CALL_PROCEEDING (CST_STATE_CAS(0x09)) /* like ITU-T Q.931: U9/N9 */
|
||||
#define CST_STATE_CAS_ACTIVE (CST_STATE_LAYER_D_L3 | CST_STATE_UP_BIT) /* like ITU-T Q.931: U10/N10 */
|
||||
#define CST_STATE_CAS_DISCONNECT_REQUEST (CST_STATE_CAS(0x0b)) /* like ITU-T Q.931: U11/N11 */
|
||||
#define CST_STATE_CAS_DISCONNECT_INDICATION (CST_STATE_CAS(0x0c)) /* like ITU-T Q.931: U12/N12 */
|
||||
#define CST_STATE_CAS_SUSPEND_REQUEST (CST_STATE_CAS(0x0f)) /* like ITU-T Q.931: U15/N15 */
|
||||
#define CST_STATE_CAS_RESUME_REQUEST (CST_STATE_CAS(0x11)) /* like ITU-T Q.931: U17/N17 */
|
||||
#define CST_STATE_CAS_RELEASE_REQUEST (CST_STATE_CAS(0x13)) /* like ITU-T Q.931: U19/N19 */
|
||||
#define CST_STATE_CAS_CALL_ABORT (CST_STATE_CAS(0x16)) /* like ITU-T Q.931: N22 */
|
||||
#define CST_STATE_CAS_OVERLAP_RECEIVING (CST_STATE_CAS(0x19)) /* like ITU-T Q.931: U25/N25 */
|
||||
#define CST_STATE_CAS_LINE_IN_USE (CST_STATE_CAS(0x3b)) /* */
|
||||
#define CST_STATE_CAS_LOCAL_REMOTE_BLOCKING (CST_STATE_CAS(0x3c)) /* */
|
||||
#define CST_STATE_CAS_LOCAL_BLOCKING (CST_STATE_CAS(0x3d)) /* */
|
||||
#define CST_STATE_CAS_REMOTE_BLOCKING (CST_STATE_CAS(0x3e)) /* */
|
||||
#define CST_STATE_X75_IDLE (CST_STATE_X75(0x00)) /* */
|
||||
#define CST_STATE_X75_AWAITING_ESTABLISHMENT (CST_STATE_X75(0x20)) /* */
|
||||
#define CST_STATE_X75_AWAITING_RELEASE (CST_STATE_X75(0x3f)) /* */
|
||||
#define CST_STATE_X75_ESTABLISHED (CST_STATE_LAYER_B_L2 | CST_STATE_UP_BIT) /* */
|
||||
#define CST_STATE_X25_PACKET_LAYER_READY (CST_STATE_X25(0x01)) /* ITU-T X.25: r1 */
|
||||
#define CST_STATE_X25_DTE_RESTART_REQUEST (CST_STATE_X25(0x02)) /* ITU-T X.25: r2 */
|
||||
#define CST_STATE_X25_DCE_RESTART_INDICATION (CST_STATE_X25(0x03)) /* ITU-T X.25: r3 */
|
||||
#define CST_STATE_X25_READY (CST_STATE_X25(0x04)) /* ITU-T X.25: p1 */
|
||||
#define CST_STATE_X25_DTE_WAITING (CST_STATE_X25(0x05)) /* ITU-T X.25: p2 */
|
||||
#define CST_STATE_X25_DCE_WAITING (CST_STATE_X25(0x06)) /* ITU-T X.25: p3 */
|
||||
#define CST_STATE_X25_DATA_TRANSFER (CST_STATE_LAYER_B_L3 | CST_STATE_UP_BIT) /* ITU-T X.25: p4 */
|
||||
#define CST_STATE_X25_CALL_COLLISION (CST_STATE_X25(0x08)) /* ITU-T X.25: p5 */
|
||||
#define CST_STATE_X25_DTE_CLEAR_REQUEST (CST_STATE_X25(0x09)) /* ITU-T X.25: p6 */
|
||||
#define CST_STATE_X25_DCE_CLEAR_INDICATION (CST_STATE_X25(0x0a)) /* ITU-T X.25: p7 */
|
||||
#define CST_STATE_X25_FLOW_CONTROL_READY (CST_STATE_X25(0x0b)) /* ITU-T X.25: d1 */
|
||||
#define CST_STATE_X25_DTE_RESET_REQUEST (CST_STATE_X25(0x0c)) /* ITU-T X.25: d2 */
|
||||
#define CST_STATE_X25_DCE_RESET_REQUEST (CST_STATE_X25(0x0d)) /* ITU-T X.25: d3 */
|
||||
/*------------------------------------------------------------------*/
|
||||
/* virtual switching definitions */
|
||||
#define VSJOIN 1
|
||||
#define VSTRANSPORT 2
|
||||
#define VSGETPARAMS 3
|
||||
#define VSCAD 1
|
||||
#define VSRXCPNAME 2
|
||||
#define VSCALLSTAT 3
|
||||
#define VSINVOKEID 4
|
||||
#define VSCLMRKS 5
|
||||
#define VSTBCTIDENT 6
|
||||
#define VSETSILINKID 7
|
||||
#define VSSAMECONTROLLER 8
|
||||
#define VSCTBYREROUTEID 9
|
||||
/* Errorcodes for VSLINKID begin */
|
||||
#define VSLINKIDRRWC 1
|
||||
#define VSLINKIDREJECT 2
|
||||
#define VSLINKIDTIMEOUT 3
|
||||
#define VSLINKIDFAILCOUNT 4
|
||||
#define VSLINKIDERROR 5
|
||||
/* Errorcodes for VSLINKID end */
|
||||
/* -----------------------------------------------------------**
|
||||
** The PROTOCOL_FEATURE_STRING in feature.h (included **
|
||||
** in prstart.sx and astart.sx) defines capabilities and **
|
||||
** features of the actual protocol code. It's used as a bit **
|
||||
** mask. **
|
||||
** The following Bits are defined: **
|
||||
** -----------------------------------------------------------*/
|
||||
#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */
|
||||
#define PROTCAP_MAN_IF 0x0002 /* Management interface implemented */
|
||||
#define PROTCAP_V_42 0x0004 /* V42 implemented */
|
||||
#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */
|
||||
#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */
|
||||
#define PROTCAP_EXTD_RXFC 0x0020 /* RxFC (Extd Flow Control), OOB Chnl */
|
||||
#define PROTCAP_VOIP 0x0040 /* VoIP (implies up to 512k DSP code) */
|
||||
#define PROTCAP_CMA_ALLPR 0x0080 /* CMA support for all NL primitives */
|
||||
#define PROTCAP_64BIT_DMA 0x0100 /* 64 Bit addresses on PCI BUS DMA */
|
||||
#define PROTCAP_FREE9 0x0200 /* not used */
|
||||
#define PROTCAP_FREE10 0x0400 /* not used */
|
||||
#define PROTCAP_FREE11 0x0800 /* not used */
|
||||
#define PROTCAP_FREE12 0x1000 /* not used */
|
||||
#define PROTCAP_FREE13 0x2000 /* not used */
|
||||
#define PROTCAP_FREE14 0x4000 /* not used */
|
||||
#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */
|
||||
/* -----------------------------------------------------------* */
|
||||
/* Onhook data transmission ETS30065901 */
|
||||
/* Message Type */
|
||||
#define CALLING_NUMBER_DELIVERY 0x04
|
||||
#define CALL_SETUP 0x80
|
||||
#define MESSAGE_WAITING_INDICATOR 0x82
|
||||
/*#define RESERVED84 0x84*/
|
||||
/*#define RESERVED85 0x85*/
|
||||
#define ADVICE_OF_CHARGE 0x86
|
||||
/*1111 0001
|
||||
to
|
||||
1111 1111
|
||||
F1H - Reserved for network operator use
|
||||
to
|
||||
FFH*/
|
||||
/* Parameter Types */
|
||||
#define DATE_AND_TIME 1
|
||||
#define CLI_PARAMETER_TYPE 2
|
||||
#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE 3
|
||||
#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE 4
|
||||
#define CALL_QUALIFIER 6
|
||||
#define NAME_PARAMETER_TYPE 7
|
||||
#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
|
||||
#define VISUAL_INDICATOR_PARAMETER_TYPE 0xb
|
||||
#define COMPLEMENTARY_CLI_PARAMETER_TYPE 0x10
|
||||
#define CALL_TYPE_PARAMETER_TYPE 0x11
|
||||
#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE 0x12
|
||||
#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE 0x13
|
||||
#define FORWARDED_CALL_TYPE_PARAMETER_TYPE 0x15
|
||||
#define TYPE_OF_CALLING_USER_PARAMETER_TYPE 0x16
|
||||
#define REDIRECTING_NUMBER_PARAMETER_TYPE 0x1a
|
||||
#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE 0xe0
|
||||
/* -----------------------------------------------------------* */
|
||||
#else
|
||||
#endif /* PC_H_INCLUDED } */
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_OS_STREAMING_PLATFORM_H__
|
||||
#define __DIVA_OS_STREAMING_PLATFORM_H__
|
||||
|
||||
#define DIVA_USERMODE 1
|
||||
#define LINUX 1
|
||||
|
||||
#if !defined(__i386__)
|
||||
#define READ_WORD(w) ( ((byte *)(w))[0] + \
|
||||
(((byte *)(w))[1]<<8) )
|
||||
|
||||
#define READ_DWORD(w) ( ((byte *)(w))[0] + \
|
||||
(((byte *)(w))[1]<<8) + \
|
||||
(((byte *)(w))[2]<<16) + \
|
||||
(((byte *)(w))[3]<<24) )
|
||||
|
||||
#define WRITE_WORD(b,w) do{ ((byte*)(b))[0]=(byte)(w); \
|
||||
((byte*)(b))[1]=(byte)((w)>>8); }while(0)
|
||||
|
||||
#define WRITE_DWORD(b,w) do{ ((byte*)(b))[0]=(byte)(w); \
|
||||
((byte*)(b))[1]=(byte)((w)>>8); \
|
||||
((byte*)(b))[2]=(byte)((w)>>16); \
|
||||
((byte*)(b))[3]=(byte)((w)>>24); }while(0)
|
||||
#else
|
||||
#define READ_WORD(w) (*(word *)(w))
|
||||
#define READ_DWORD(w) (*(dword *)(w))
|
||||
#define WRITE_WORD(b,w) do{ *(word *)(b)=(w); }while(0)
|
||||
#define WRITE_DWORD(b,w) do{ *(dword *)(b)=(w); }while(0)
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned int dword;
|
||||
typedef signed int int32;
|
||||
typedef unsigned long long qword;
|
||||
|
||||
#ifndef likely
|
||||
#define likely(__x__) (!!(__x__))
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(__x__) (!!(__x__))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)>(b) ? (b) : (a))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define DIVAS_CONTAINING_RECORD(address, type, field) \
|
||||
((type *)((char*)(address) - (char*)(&((type *)0)->field)))
|
||||
|
||||
#define DIVA_STREAMING_MAX_TRACE_IDENT_LENGTH 4
|
||||
|
||||
void* diva_os_malloc (unsigned long flags, unsigned long size);
|
||||
void diva_os_free (unsigned long flags, void* ptr);
|
||||
|
||||
#define _DI_STREAM_CTRL 0x0014
|
||||
|
||||
#include <string.h>
|
||||
#include "debuglib.h"
|
||||
|
||||
#define DIVA_SHARED_SEGMENT_ALLOC 1
|
||||
/*
|
||||
DIVA_SHARED_SEGMENT_LOCK used to lock shared segment alloc instance. Locked instance is newer freed
|
||||
due to reference counter newer receives zero. This allows to maintain permenently mapped pool of pages
|
||||
and to reduce overall system load.
|
||||
Causes memory load if application is stopped, but memory and mapped resources are freed by OS.
|
||||
*/
|
||||
#define DIVA_SHARED_SEGMENT_LOCK 1
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2011
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "platform.h"
|
||||
#include <malloc.h>
|
||||
#include "chan_capi_platform.h"
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
#include "chan_capi_utils.h"
|
||||
|
||||
void* diva_os_malloc (unsigned long flags, unsigned long size) {
|
||||
void* ret = 0;
|
||||
|
||||
if (size != 0) {
|
||||
ret = ast_malloc (size);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void diva_os_free (unsigned long flags, void* ptr) {
|
||||
if (ptr != 0) {
|
||||
ast_free (ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void diva_runtime_error_message (const char* fmt, ...) {
|
||||
char tmp[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||
va_end(ap);
|
||||
tmp[sizeof(tmp)-1]=0;
|
||||
|
||||
cc_log(LOG_ERROR, "%s\n", tmp);
|
||||
}
|
||||
|
||||
void diva_runtime_log_message (const char* fmt, ...) {
|
||||
char tmp[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||
va_end(ap);
|
||||
tmp[sizeof(tmp)-1]=0;
|
||||
|
||||
cc_verbose(4, 0, "%s\n", tmp);
|
||||
}
|
||||
|
||||
void diva_runtime_trace_message (const char* fmt, ...) {
|
||||
char tmp[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||
va_end(ap);
|
||||
tmp[sizeof(tmp)-1]=0;
|
||||
|
||||
cc_verbose(4, 1, "%s\n", tmp);
|
||||
}
|
||||
|
||||
void diva_runtime_binary_message (const void* data, unsigned long data_length) {
|
||||
static const char hex_digit_table[0x10] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
word i, j;
|
||||
char *p;
|
||||
char hex_line[50];
|
||||
const byte *buffer = data;
|
||||
word length = (word)data_length;
|
||||
|
||||
for (i = 0; i < length; i += 16) {
|
||||
p = hex_line;
|
||||
for (j = 0; (j < 16) && (i+j < length); j++) {
|
||||
*(p++) = ' ';
|
||||
*(p++) = hex_digit_table[buffer[i+j] >> 4];
|
||||
*(p++) = hex_digit_table[buffer[i+j] & 0xf];
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
cc_verbose(4, 1, "[%02x]%s\n", (unsigned int) i, hex_line);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* vim:ts=2:
|
||||
*/
|
||||
#include "platform.h"
|
||||
#include "dlist.h"
|
||||
#include "diva_segment_alloc_ifc.h"
|
||||
#ifdef DIVA_USERMODE
|
||||
#include "xdi_msg.h"
|
||||
#else
|
||||
#include "pc.h"
|
||||
#include "di_defs.h"
|
||||
#include "divasync.h"
|
||||
#endif
|
||||
#include "debuglib.h"
|
||||
|
||||
#if defined(LINUX) && defined(DIVA_USERMODE)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef struct _diva_map_entry {
|
||||
diva_entity_link_t link;
|
||||
int entry_nr;
|
||||
dword dma_lo;
|
||||
dword dma_hi;
|
||||
void* mem;
|
||||
} diva_map_entry_t;
|
||||
|
||||
typedef struct _diva_segment_alloc {
|
||||
diva_segment_alloc_access_t ifc;
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
int fd;
|
||||
int fd_mem;
|
||||
int fd_xdi;
|
||||
#endif
|
||||
#else
|
||||
DESCRIPTOR* d;
|
||||
#endif
|
||||
diva_entity_queue_t free_q;
|
||||
diva_entity_queue_t busy_q;
|
||||
#if !defined(DIVA_USERMODE)
|
||||
IDI_SYNC_REQ syncReq;
|
||||
#endif
|
||||
} diva_segment_alloc_t;
|
||||
|
||||
/*
|
||||
* LOCALS
|
||||
*/
|
||||
static void release_proc(struct _diva_segment_alloc**);
|
||||
static void* segment_alloc_proc(struct _diva_segment_alloc*, dword* lo, dword* hi);
|
||||
static void segment_free_proc(struct _diva_segment_alloc*, void* addr, dword lo, dword hi);
|
||||
static dword get_segment_length_proc(struct _diva_segment_alloc*);
|
||||
#if defined(DIVA_USERMODE)
|
||||
static int map_entry (struct _diva_segment_alloc* pI, diva_map_entry_t* pE);
|
||||
#endif
|
||||
static void* map_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, int map_host);
|
||||
static void* umap_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local);
|
||||
static int write_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, dword data);
|
||||
static void resource_removed (struct _diva_segment_alloc* ifc);
|
||||
|
||||
#if !defined(DIVA_USERMODE)
|
||||
static void diva_segment_allloc_resource_removed_request(ENTITY* e) { }
|
||||
static DESCRIPTOR diva_segment_alloc_resource_removed_descriptor =
|
||||
{ 0, 0, 0, diva_segment_allloc_resource_removed_request };
|
||||
#endif
|
||||
|
||||
static diva_segment_alloc_access_t ifc_ref = {
|
||||
release_proc,
|
||||
segment_alloc_proc,
|
||||
segment_free_proc,
|
||||
get_segment_length_proc,
|
||||
map_address,
|
||||
umap_address,
|
||||
write_address,
|
||||
resource_removed
|
||||
};
|
||||
|
||||
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
|
||||
static struct _diva_segment_alloc* shared_segment_alloc;
|
||||
static int shared_segment_alloc_count;
|
||||
#endif
|
||||
|
||||
int diva_create_segment_alloc (void* os_context, struct _diva_segment_alloc** segment_alloc)
|
||||
{
|
||||
diva_segment_alloc_t* pI = diva_os_malloc(0, sizeof(*pI));
|
||||
|
||||
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
|
||||
if (shared_segment_alloc != 0) {
|
||||
shared_segment_alloc_count++;
|
||||
*segment_alloc = shared_segment_alloc;
|
||||
DBG_TRC(("shared %d segment alloc [%p]", shared_segment_alloc_count, pI))
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
pI = diva_os_malloc(0, sizeof(*pI));
|
||||
|
||||
if (pI != 0) {
|
||||
memset (pI, 0x00, sizeof(*pI));
|
||||
|
||||
pI->ifc = ifc_ref;
|
||||
|
||||
diva_q_init (&pI->free_q);
|
||||
diva_q_init (&pI->busy_q);
|
||||
|
||||
#if defined(DIVA_USERMODE) /* { */
|
||||
#if defined(LINUX) /* { */
|
||||
pI->fd = open ("/dev/DivasMAP", O_RDWR | O_NONBLOCK); /** \todo use hardware related DMA entry, needs update of XDI driver */
|
||||
pI->fd_mem = open ("/dev/mem", O_RDWR | O_NONBLOCK); /* /dev/mem is optional */
|
||||
pI->fd_xdi = open ("/dev/DivasXDI", O_RDWR | O_NONBLOCK); /* /dev/mem is optional */
|
||||
|
||||
if (pI->fd >= 0 && (pI->fd_mem >= 0 || pI->fd_xdi >= 0)) {
|
||||
*segment_alloc = pI;
|
||||
} else {
|
||||
diva_destroy_segment_alloc (&pI);
|
||||
pI = 0;
|
||||
}
|
||||
#endif /* } */
|
||||
#else /* } { */
|
||||
pI->d = (DESCRIPTOR*)os_context;
|
||||
*segment_alloc = pI;
|
||||
#endif /* } */
|
||||
}
|
||||
|
||||
if (pI != 0) {
|
||||
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
|
||||
shared_segment_alloc = pI;
|
||||
shared_segment_alloc_count = 1;
|
||||
#if defined(DIVA_SHARED_SEGMENT_LOCK)
|
||||
shared_segment_alloc_count++;
|
||||
#endif
|
||||
#endif
|
||||
DBG_TRC(("created segment alloc [%p]", pI))
|
||||
}
|
||||
|
||||
return ((pI != 0) ? 0 : -1);
|
||||
}
|
||||
|
||||
int diva_destroy_segment_alloc (struct _diva_segment_alloc** segment_alloc) {
|
||||
diva_segment_alloc_t* pI = (segment_alloc != 0) ? *segment_alloc : 0;
|
||||
|
||||
#if defined(DIVA_SHARED_SEGMENT_ALLOC)
|
||||
shared_segment_alloc_count--;
|
||||
if (shared_segment_alloc_count > 0) {
|
||||
if (segment_alloc != 0)
|
||||
*segment_alloc = 0;
|
||||
DBG_TRC(("unshare %d segment alloc [%p]", shared_segment_alloc_count, segment_alloc))
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
DBG_TRC(("destroy segment alloc [%p]", segment_alloc))
|
||||
|
||||
if (pI != 0) {
|
||||
diva_entity_link_t* link;
|
||||
|
||||
shared_segment_alloc = 0;
|
||||
shared_segment_alloc_count = 0;
|
||||
|
||||
while ((link = diva_q_get_head (&pI->busy_q)) != 0) {
|
||||
diva_q_remove (&pI->busy_q, link);
|
||||
diva_q_add_tail (&pI->free_q, link);
|
||||
}
|
||||
|
||||
while ((link = diva_q_get_head (&pI->free_q)) != 0) {
|
||||
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
munmap (pE->mem, 4*1024);
|
||||
#endif
|
||||
#else
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING_FREE_COMMAND;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = pE->dma_lo;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = pE->dma_hi;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = pE->mem;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = pE->entry_nr;
|
||||
pI->d->request((ENTITY*)&pI->syncReq);
|
||||
#endif
|
||||
diva_q_remove (&pI->free_q, link);
|
||||
diva_os_free (0, pE);
|
||||
}
|
||||
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
if (pI->fd >= 0)
|
||||
close (pI->fd);
|
||||
if (pI->fd_mem >= 0)
|
||||
close (pI->fd_mem);
|
||||
if (pI->fd_xdi >= 0)
|
||||
close (pI->fd_xdi);
|
||||
#endif
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
diva_os_free (0, pI);
|
||||
|
||||
*segment_alloc = 0;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void release_proc(struct _diva_segment_alloc** pI) {
|
||||
diva_destroy_segment_alloc (pI);
|
||||
}
|
||||
|
||||
void* segment_alloc_proc(struct _diva_segment_alloc* pI, dword* lo, dword* hi) {
|
||||
diva_entity_link_t* link = diva_q_get_head(&pI->free_q);
|
||||
void* addr = 0;
|
||||
|
||||
if (link != 0) {
|
||||
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
|
||||
|
||||
diva_q_remove (&pI->free_q, link);
|
||||
diva_q_add_tail (&pI->busy_q, link);
|
||||
|
||||
*lo = pE->dma_lo;
|
||||
*hi = pE->dma_hi;
|
||||
|
||||
return (pE->mem);
|
||||
} else if ((link = diva_os_malloc (0, sizeof(diva_map_entry_t))) != 0) {
|
||||
diva_map_entry_t* pE = (diva_map_entry_t*)link;
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
dword data[5];
|
||||
int ret;
|
||||
|
||||
data[0] = DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS;
|
||||
data[1] = 1;
|
||||
|
||||
{ int tmp = write (pI->fd, data, 2*sizeof(dword)); tmp++; }
|
||||
ret = read (pI->fd, data, sizeof(data));
|
||||
if (ret == sizeof(data) || ret == (sizeof(data)-sizeof(data[0]))) {
|
||||
if (data[0] == DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS && data[1] == 1) {
|
||||
pE->dma_lo = data[3];
|
||||
pE->dma_hi = (data[2] == 8) ? data[4] : 0;
|
||||
if (map_entry(pI, pE) == 0) {
|
||||
diva_q_add_tail (&pI->busy_q, &pE->link);
|
||||
*lo = pE->dma_lo;
|
||||
*hi = pE->dma_hi;
|
||||
addr = pE->mem;
|
||||
} else {
|
||||
diva_os_free (0, pE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING_ALLOC_COMMAND;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = -1;
|
||||
pI->d->request((ENTITY*)&pI->syncReq);
|
||||
if (pI->syncReq.diva_xdi_streaming_mapping_req.info.request == IDI_SYNC_REQ_PROCESS_STREAMING_COMMAND_OK &&
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr != 0) {
|
||||
pE->entry_nr = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle;
|
||||
pE->dma_lo = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo;
|
||||
pE->dma_hi = pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi;
|
||||
pE->mem = pI->syncReq.diva_xdi_streaming_mapping_req.info.addr;
|
||||
|
||||
*lo = pE->dma_lo;
|
||||
*hi = pE->dma_hi;
|
||||
addr = pE->mem;
|
||||
|
||||
memset (addr, 0x00, 4*1024);
|
||||
|
||||
diva_q_add_tail (&pI->busy_q, &pE->link);
|
||||
} else {
|
||||
diva_os_free (0, pE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (addr);
|
||||
}
|
||||
|
||||
#if defined(DIVA_USERMODE)
|
||||
static int map_entry (struct _diva_segment_alloc* pI, diva_map_entry_t* pE) {
|
||||
void* addr;
|
||||
|
||||
if (pE->dma_hi != 0) {
|
||||
qword i = ((qword)pE->dma_lo) | (((qword)pE->dma_hi) << 32);
|
||||
#if defined(LINUX)
|
||||
addr = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, pI->fd, i);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(LINUX)
|
||||
addr = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, pI->fd, pE->dma_lo);
|
||||
#endif
|
||||
}
|
||||
if (addr == 0 || addr == ((void*)-1)) {
|
||||
DBG_ERR(("failed to map %08x:%08x [%p]", pE->dma_lo, pE->dma_hi, pI))
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
pE->mem = addr;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* map_address (struct _diva_segment_alloc* pI, dword lo, dword hi, int map_host) {
|
||||
void* ret = 0;
|
||||
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
qword addr = ((qword)lo) | (((qword)hi) << 32);
|
||||
int effective_map_fd = (map_host == 0) ? pI->fd_mem : pI->fd;
|
||||
|
||||
if (effective_map_fd >= 0) {
|
||||
ret = mmap (0, 4*1024, PROT_READ|PROT_WRITE, MAP_SHARED, effective_map_fd, addr);
|
||||
if (ret == ((void*)-1)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Req = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.Rc = IDI_SYNC_REQ_PROCESS_STREAMING_MAPPING;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.request = IDI_SYNC_REQ_PROCESS_STREAMING_SYSTEM_MAP_COMMAND;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_handle = -1;
|
||||
pI->d->request((ENTITY*)&pI->syncReq);
|
||||
if (pI->syncReq.diva_xdi_streaming_mapping_req.info.request == IDI_SYNC_REQ_PROCESS_STREAMING_COMMAND_OK) {
|
||||
byte* p = pI->syncReq.diva_xdi_streaming_mapping_req.info.addr;
|
||||
dword offset = lo - pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo;
|
||||
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.addr = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_lo = 0;
|
||||
pI->syncReq.diva_xdi_streaming_mapping_req.info.dma_hi = 0;
|
||||
|
||||
ret = p + offset;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void* umap_address (struct _diva_segment_alloc* ifc, dword lo, dword hi, void* local) {
|
||||
#if defined(DIVA_USERMODE)
|
||||
#if defined(LINUX)
|
||||
munmap (local, 4*1024);
|
||||
#endif
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int write_address (struct _diva_segment_alloc* pI, dword lo, dword hi, dword data) {
|
||||
diva_xdi_direct_access_cmd_t cmd;
|
||||
int ret;
|
||||
|
||||
if (unlikely(pI->fd_xdi < 0))
|
||||
return (-1);
|
||||
|
||||
|
||||
cmd.hdr.ident = DIVA_XDI_DIRECT_ACCESS_CMD_IDENT;
|
||||
cmd.hdr.cmd = DIVA_XDI_DIRECT_ACCESS_CMD_WRITE_BY_ADDRESS;
|
||||
cmd.cmd.write_by_address.address = lo;
|
||||
cmd.cmd.write_by_address.value = data;
|
||||
|
||||
ret = write (pI->fd_xdi, &cmd, sizeof(cmd.hdr)+sizeof(cmd.cmd.write_by_address)) ==
|
||||
sizeof(cmd.hdr)+sizeof(cmd.cmd.write_by_address) ? 0 : -1;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void resource_removed (struct _diva_segment_alloc* pI) {
|
||||
#if defined(DIVA_USERMODE)
|
||||
|
||||
#else
|
||||
pI->d = &diva_segment_alloc_resource_removed_descriptor;
|
||||
#endif
|
||||
}
|
||||
|
||||
void segment_free_proc(struct _diva_segment_alloc* pI, void* addr, dword lo, dword hi) {
|
||||
diva_entity_link_t* link;
|
||||
|
||||
for (link = diva_q_get_head(&pI->busy_q); link != 0; link = diva_q_get_next(link)) {
|
||||
diva_map_entry_t* pE = DIVAS_CONTAINING_RECORD(link, diva_map_entry_t, link);
|
||||
|
||||
if (pE->mem == addr && pE->dma_lo == lo && pE->dma_hi == hi) {
|
||||
diva_q_remove (&pI->busy_q, link);
|
||||
diva_q_add_tail (&pI->free_q, link);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DBG_ERR(("segment not found: %p %08x:%08x [%p]", addr, lo, hi, pI))
|
||||
}
|
||||
|
||||
dword get_segment_length_proc(struct _diva_segment_alloc* pI) {
|
||||
return (4*1024);
|
||||
}
|
||||
|
||||
diva_segment_alloc_access_t* diva_get_segment_alloc_ifc (struct _diva_segment_alloc* segment_alloc) {
|
||||
return ((segment_alloc != 0) ? &segment_alloc->ifc : 0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic (R) 2009 - 2010
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Eicon Networks range of DIVA Server Adapters.
|
||||
*
|
||||
Dialogic (R) File Revision : 1.9
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_SPI_DESCRIPTOR_H__
|
||||
#define __DIVA_SPI_DESCRIPTOR_H__
|
||||
|
||||
|
||||
#define MAX_SPI_DESCRIPTOR_LENGTH (4*1024)
|
||||
#define MAX_XCONN_PER_DSP_DESCRIPTORS 8
|
||||
#define SMALL_FLAT_RX_BUFFER_LENGTH 128
|
||||
|
||||
/*
|
||||
SPI descriptor is always transferred in two parts:
|
||||
byte* msg;
|
||||
|
||||
xmit(&msg[4], length-4);
|
||||
xmit(msg, 4);
|
||||
|
||||
The second transfer is used as indication about end of the
|
||||
descriptor transfer.
|
||||
*/
|
||||
|
||||
typedef struct _diva_spi_msg_hdr {
|
||||
byte length_lo; /* Total transfer length, includes the the length of the header, lo byte */
|
||||
byte length_hi; /* Total transfer length, includes the length of the header, h byte */
|
||||
byte Id; /* IDI Id. 0xff in case of the system message */
|
||||
byte Ind; /* Ind */
|
||||
} diva_spi_msg_hdr_t;
|
||||
|
||||
typedef struct _diva_spi_msg {
|
||||
diva_spi_msg_hdr_t hdr;
|
||||
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_spi_msg_hdr_t)];
|
||||
} diva_spi_msg_t;
|
||||
|
||||
/*
|
||||
System messages:
|
||||
if Id == 0xff then system message
|
||||
if (length_hi & 0x80) then system message is chained after the message
|
||||
|
||||
Messages:
|
||||
byte - message type
|
||||
byte - message length without this byte and the length byte
|
||||
body - sequence of bytes, depends on the type of message
|
||||
*/
|
||||
|
||||
/*
|
||||
Used for comminication with
|
||||
monitor task
|
||||
*/
|
||||
typedef struct _diva_dsp_monitor_message_hdr {
|
||||
byte length_lo; /* Total transfer length, includes the the length of the header, lo byte */
|
||||
byte length_hi; /* Total transfer length, includes the length of the header, h byte */
|
||||
byte message_lo;
|
||||
byte message_hi;
|
||||
} diva_dsp_monitor_message_hdr_t;
|
||||
|
||||
typedef struct _diva_dsp_monitor_message {
|
||||
diva_dsp_monitor_message_hdr_t hdr;
|
||||
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_dsp_monitor_message_hdr_t)];
|
||||
} diva_dsp_monitor_message_t;
|
||||
|
||||
/*
|
||||
Format of the request:
|
||||
length_lo
|
||||
length_hi - set to "data_length + 5"
|
||||
Id
|
||||
Req - Stored in the Ind field
|
||||
RegCh - Req Ch stored in the first byte of data field
|
||||
data - first byte of data
|
||||
*/
|
||||
|
||||
/*
|
||||
Format of the return code without extended info:
|
||||
length_lo
|
||||
length_hi - set to 6
|
||||
Id
|
||||
Rc - Stored in the Ind field
|
||||
RcCh - RcCh stored in the first byte of data field
|
||||
type - Type. Set to zero for RC, stored in the second byte of data field
|
||||
|
||||
Format of the return code with extended info:
|
||||
length_lo
|
||||
length_hi - set to 14
|
||||
Id
|
||||
Rc - Stored in the Ind field
|
||||
RcCh - RcCh stored in the first byte of data field
|
||||
type - Type. Set to zero for RC, stored in the second byte of data field
|
||||
dword - extended info type (bytes 2,3,4,5 of data field)
|
||||
dword - extended info (bytes 6,7,8,9 of data field)
|
||||
*/
|
||||
|
||||
/*
|
||||
Format of the indication:
|
||||
length_lo
|
||||
length_hi - set to "data_lengt + 6"
|
||||
Id
|
||||
Ind - Stored in the Ind field
|
||||
IndCh - IndCh stored in the first byte of data field
|
||||
type - Type. Set to one for IND, stored in the second byte of data field
|
||||
data - first byte of data, starts at third data byte
|
||||
*/
|
||||
|
||||
typedef struct _diva_xconn_msg_hdr {
|
||||
word counter;
|
||||
word length;
|
||||
} diva_xconn_msg_hdr_t;
|
||||
|
||||
typedef struct _diva_xconn_msg {
|
||||
diva_xconn_msg_hdr_t hdr;
|
||||
byte data[MAX_SPI_DESCRIPTOR_LENGTH-sizeof(diva_xconn_msg_hdr_t)];
|
||||
} diva_xconn_msg_t;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,338 @@
|
|||
|
||||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2010-2011
|
||||
Copyright 2000-2003 by Armin Schindler (mac@melware.de)
|
||||
Copyright 2000-2003 Cytronics & Melware (info@melware.de)
|
||||
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Dialogic range of Adapters.
|
||||
*
|
||||
Dialogic(R) File Revision : 2.1
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DIVA_XDI_UM_CFG_MESSSGE_H__
|
||||
#define __DIVA_XDI_UM_CFG_MESSAGE_H__
|
||||
|
||||
/*
|
||||
Definition of commands for user mode configuration
|
||||
utility to XDI device driver
|
||||
*/
|
||||
|
||||
/*
|
||||
XDI WRITE command
|
||||
*/
|
||||
#define DIVA_XDI_IO_CMD_WRITE_MSG 0x3701
|
||||
|
||||
/*
|
||||
XDI READ command
|
||||
*/
|
||||
#define DIVA_XDI_IO_CMD_READ_MSG 0x3702
|
||||
|
||||
|
||||
/*
|
||||
Definition of messages used to communicate between
|
||||
XDI device driver and user mode configuration utility
|
||||
*/
|
||||
|
||||
/*
|
||||
As acknowledge one DWORD - card ordinal will be read from the card
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_CARD_ORDINAL 0
|
||||
|
||||
/*
|
||||
no acknowledge will be generated, memory block will be written in the
|
||||
memory at given offset
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK 1
|
||||
|
||||
/*
|
||||
no acknowledge will be genatated, FPGA will be programmed
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_WRITE_FPGA 2
|
||||
|
||||
/*
|
||||
As acknowledge block of SDRAM will be read in the user buffer
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_READ_SDRAM 3
|
||||
|
||||
/*
|
||||
As acknowledge dword with serial number will be read in the user buffer
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_SERIAL_NR 4
|
||||
|
||||
/*
|
||||
As acknowledge struct consisting from 9 dwords with PCI info.
|
||||
dword[0...7] = 8 PCI BARS
|
||||
dword[9] = IRQ
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG 5
|
||||
|
||||
/*
|
||||
Reset of the board + activation of primary
|
||||
boot loader
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_RESET_ADAPTER 6
|
||||
|
||||
/*
|
||||
Called after code download to start adapter
|
||||
at specified address
|
||||
Start does set new set of features due to fact that we not know
|
||||
if protocol features have changed
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_START_ADAPTER 7
|
||||
|
||||
/*
|
||||
Stop adapter, called if user
|
||||
wishes to stop adapter without unload
|
||||
of the driver, to reload adapter with
|
||||
different protocol
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_STOP_ADAPTER 8
|
||||
|
||||
/*
|
||||
Get state of current adapter
|
||||
Acknowledge is one dword with following values:
|
||||
0 - adapter ready for download
|
||||
1 - adapter running
|
||||
2 - adapter dead
|
||||
3 - out of service, driver should be restarted or hardware problem
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_CARD_STATE 9
|
||||
|
||||
/*
|
||||
Reads XLOG entry from the card
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_READ_XLOG_ENTRY 10
|
||||
|
||||
/*
|
||||
Set untranslated protocol code features
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES 11
|
||||
|
||||
/*
|
||||
Start adapter test procedure
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_ADAPTER_TEST 12
|
||||
|
||||
/*
|
||||
Alloc DMA descriptor
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_ALLOC_DMA_DESCRIPTOR 14
|
||||
|
||||
|
||||
/*
|
||||
Get hardware information structure
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_HW_INFO_STRUCT 15
|
||||
|
||||
/*
|
||||
Change XDI driver protocol code version
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_SET_PROTOCOL_CODE_VERSION 17
|
||||
|
||||
/*
|
||||
Init VIDI, read VIDI info from driver
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_INIT_VIDI 18
|
||||
|
||||
/*
|
||||
Select VIDI mode
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_SET_VIDI_MODE 19
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_set_vidi_mode {
|
||||
dword vidi_mode;
|
||||
} diva_xdi_um_cfg_cmd_set_vidi_mode_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_init_vidi {
|
||||
dword req_magic_lo;
|
||||
dword req_magic_hi;
|
||||
dword ind_magic_lo;
|
||||
dword ind_magic_hi;
|
||||
|
||||
dword dma_segment_length;
|
||||
dword dma_req_buffer_length;
|
||||
dword dma_ind_buffer_length;
|
||||
dword dma_ind_remote_counter_offset;
|
||||
} diva_xdi_um_cfg_cmd_data_init_vidi_t;
|
||||
|
||||
/*
|
||||
Get clock memory info
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_GET_CLOCK_MEMORY_INFO 20
|
||||
|
||||
/*
|
||||
Read PLX register
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_READ_WRITE_PLX_REGISTER 21
|
||||
|
||||
/*
|
||||
Create DMA descriptor
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_CREATE_XDI_DESCRIPTORS 22
|
||||
|
||||
/*
|
||||
Clock interrupt
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_CLOCK_INTERRUPT_CONTROL 23
|
||||
|
||||
/*
|
||||
Clock interrupt data
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_CLOCK_INTERRUPT_DATA 24
|
||||
|
||||
/*
|
||||
BAR Access
|
||||
*/
|
||||
#define DIVA_XDI_UM_CMD_BAR_ACCESS 25
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_get_clock_memory_info {
|
||||
dword bus_addr_lo;
|
||||
dword bus_addr_hi;
|
||||
dword length;
|
||||
} diva_xdi_um_cfg_cmd_get_clock_memory_info_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor {
|
||||
dword nr;
|
||||
dword low;
|
||||
dword high;
|
||||
} diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_adapter_test {
|
||||
dword test_command;
|
||||
} diva_xdi_um_cfg_cmd_data_adapter_test_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_set_features {
|
||||
dword features;
|
||||
} diva_xdi_um_cfg_cmd_data_set_features_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_start {
|
||||
dword offset;
|
||||
dword features;
|
||||
} diva_xdi_um_cfg_cmd_data_start_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_write_sdram {
|
||||
dword ram_number;
|
||||
dword offset;
|
||||
dword length;
|
||||
} diva_xdi_um_cfg_cmd_data_write_sdram_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_write_fpga {
|
||||
dword fpga_number;
|
||||
dword image_length;
|
||||
} diva_xdi_um_cfg_cmd_data_write_fpga_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_read_sdram {
|
||||
dword ram_number;
|
||||
dword offset;
|
||||
dword length;
|
||||
} diva_xdi_um_cfg_cmd_data_read_sdram_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_data_set_protocol_code_version {
|
||||
dword version;
|
||||
} diva_xdi_um_cfg_cmd_data_set_protocol_code_version_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_read_write_plx_register {
|
||||
byte write;
|
||||
byte offset;
|
||||
byte length;
|
||||
dword value;
|
||||
} diva_xdi_um_cfg_cmd_read_write_plx_register_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_clock_interrupt_control {
|
||||
dword command;
|
||||
} diva_xdi_um_cfg_cmd_clock_interrupt_control_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd_get_clock_interrupt_data {
|
||||
dword state;
|
||||
dword clock;
|
||||
dword errors;
|
||||
} diva_xdi_um_cfg_cmd_get_clock_interrupt_data_t;
|
||||
|
||||
#define DIVA_BAR_ACCESS_TYPE_READ 0x00
|
||||
#define DIVA_BAR_ACCESS_TYPE_WRITE 0x01
|
||||
#define DIVA_BAR_ACCESS_TYPE_SINGLE 0x02
|
||||
#define DIVA_BAR_ACCESS_TYPE_BYTE 0x04
|
||||
#define DIVA_BAR_ACCESS_TYPE_WORD 0x08
|
||||
#define DIVA_BAR_ACCESS_TYPE_DWORD 0x10
|
||||
#define DIVA_BAR_ACCESS_TYPE_WRITE_READ 0x20
|
||||
|
||||
typedef struct _diva_xdi_um_bar_access_data {
|
||||
byte bar;
|
||||
byte access_type;
|
||||
word length;
|
||||
dword offset;
|
||||
dword data;
|
||||
} diva_xdi_um_bar_access_data_t;
|
||||
|
||||
typedef union _diva_xdi_um_cfg_cmd_data {
|
||||
diva_xdi_um_cfg_cmd_data_write_sdram_t write_sdram;
|
||||
diva_xdi_um_cfg_cmd_data_write_fpga_t write_fpga;
|
||||
diva_xdi_um_cfg_cmd_data_read_sdram_t read_sdram;
|
||||
diva_xdi_um_cfg_cmd_data_start_t start;
|
||||
diva_xdi_um_cfg_cmd_data_set_features_t features;
|
||||
diva_xdi_um_cfg_cmd_data_adapter_test_t test;
|
||||
diva_xdi_um_cfg_cmd_data_alloc_dma_descriptor_t dma;
|
||||
diva_xdi_um_cfg_cmd_data_set_protocol_code_version_t protocol_code_version;
|
||||
diva_xdi_um_cfg_cmd_data_init_vidi_t vidi;
|
||||
diva_xdi_um_cfg_cmd_set_vidi_mode_t vidi_mode;
|
||||
diva_xdi_um_cfg_cmd_get_clock_memory_info_t clock_memory;
|
||||
diva_xdi_um_cfg_cmd_read_write_plx_register_t plx_register;
|
||||
diva_xdi_um_cfg_cmd_clock_interrupt_control_t clock_interrupt_control;
|
||||
diva_xdi_um_cfg_cmd_get_clock_interrupt_data_t clock_interrupt_data;
|
||||
diva_xdi_um_bar_access_data_t bar_access_data;
|
||||
} diva_xdi_um_cfg_cmd_data_t;
|
||||
|
||||
typedef struct _diva_xdi_um_cfg_cmd {
|
||||
dword adapter; /* Adapter number 1...N */
|
||||
dword command;
|
||||
diva_xdi_um_cfg_cmd_data_t command_data;
|
||||
dword data_length; /* Plain binary data will follow */
|
||||
} diva_xdi_um_cfg_cmd_t;
|
||||
|
||||
typedef struct _diva_xdi_io_cmd {
|
||||
unsigned int length;
|
||||
void * cmd;
|
||||
} diva_xdi_io_cmd;
|
||||
|
||||
/*
|
||||
* Diva direct interface access commands
|
||||
*/
|
||||
#define DIVA_XDI_DIRECT_ACCESS_CMD_IDENT 0x1234abcd
|
||||
typedef struct _diva_xdi_direct_access_cmd_hdr {
|
||||
dword ident;
|
||||
dword cmd;
|
||||
} diva_xdi_direct_access_cmd_hdr_t;
|
||||
|
||||
#define DIVA_XDI_DIRECT_ACCESS_CMD_WRITE_BY_ADDRESS 1
|
||||
typedef struct _diva_xdi_direct_access_write_by_address {
|
||||
dword address;
|
||||
dword value;
|
||||
} diva_xdi_direct_access_write_by_address_t;
|
||||
|
||||
typedef struct _diva_xdi_direct_access_cmd {
|
||||
diva_xdi_direct_access_cmd_hdr_t hdr;
|
||||
union {
|
||||
diva_xdi_direct_access_write_by_address_t write_by_address;
|
||||
} cmd;
|
||||
} diva_xdi_direct_access_cmd_t;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2011
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Implements interface to diva trace system
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "chan_capi20.h"
|
||||
#include "chan_capi.h"
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_4
|
||||
#include <asterisk.h>
|
||||
#endif
|
||||
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "divaverbose.h"
|
||||
|
||||
static int verbose_registered;
|
||||
AST_MUTEX_DEFINE_STATIC(dbgIfcLock);
|
||||
static volatile int divaDbgIfc = -1;
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static
|
||||
#endif
|
||||
char capi_do_verbose_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " verbose\n"
|
||||
" Connect to debug driver.\n";
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
static
|
||||
#endif
|
||||
char capi_no_verbose_usage[] =
|
||||
"Usage: " CC_MESSAGE_NAME " no verbose\n"
|
||||
" Disconnect from debug driver.\n";
|
||||
|
||||
static void open_diva_mnt(void)
|
||||
{
|
||||
cc_mutex_lock(&dbgIfcLock);
|
||||
if (divaDbgIfc < 0) {
|
||||
divaDbgIfc = open("/dev/DivasDBGIFC", O_WRONLY);
|
||||
}
|
||||
cc_mutex_unlock(&dbgIfcLock);
|
||||
}
|
||||
|
||||
#if (!defined(CC_AST_HAS_VERSION_1_4) && !defined(CC_AST_HAS_VERSION_1_6) && !defined(CC_AST_HAS_VERSION_1_8))
|
||||
static void diva_verbose_write (const char *info, int opos, int replacelast, int complete)
|
||||
#else
|
||||
static void diva_verbose_write (const char *info)
|
||||
#endif
|
||||
{
|
||||
if (divaDbgIfc < 0) {
|
||||
open_diva_mnt();
|
||||
}
|
||||
if (divaDbgIfc >= 0) {
|
||||
write (divaDbgIfc, info, strlen(info));
|
||||
}
|
||||
}
|
||||
|
||||
static int diva_verbose_start(void)
|
||||
{
|
||||
if (verbose_registered == 0) {
|
||||
verbose_registered = (ast_register_verbose(diva_verbose_write) == 0);
|
||||
}
|
||||
|
||||
return ((verbose_registered != 0) ? 0 : -1);
|
||||
}
|
||||
|
||||
static int diva_verbose_stop(void)
|
||||
{
|
||||
if (verbose_registered != 0) {
|
||||
verbose_registered = !(ast_unregister_verbose(diva_verbose_write) == 0);
|
||||
}
|
||||
if ((verbose_registered == 0) && (divaDbgIfc >= 0)) {
|
||||
close(divaDbgIfc);
|
||||
divaDbgIfc = -1;
|
||||
}
|
||||
|
||||
return ((verbose_registered == 0) ? 0 : -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* enable debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
char *pbxcli_capi_do_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
int pbxcli_capi_do_verbose(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " verbose";
|
||||
e->usage = capi_do_verbose_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 2)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
ret = diva_verbose_start();
|
||||
if (ret == 0) {
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Verboser Enabled\n");
|
||||
} else {
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Failed to enable Message Verboser\n");
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
|
||||
#else
|
||||
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* disable debugging
|
||||
*/
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
char *pbxcli_capi_no_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
||||
#else
|
||||
int pbxcli_capi_no_verbose(int fd, int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
int fd = a->fd;
|
||||
|
||||
if (cmd == CLI_INIT) {
|
||||
e->command = CC_MESSAGE_NAME " no verbose";
|
||||
e->usage = capi_no_verbose_usage;
|
||||
return NULL;
|
||||
} else if (cmd == CLI_GENERATE)
|
||||
return NULL;
|
||||
if (a->argc != e->args)
|
||||
return CLI_SHOWUSAGE;
|
||||
#else
|
||||
if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
#endif
|
||||
|
||||
|
||||
ret = diva_verbose_stop();
|
||||
if (ret == 0) {
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Message Verboser Disabled\n");
|
||||
} else {
|
||||
ast_cli(fd, CC_MESSAGE_BIGNAME " Failed to disable Message Verboser\n");
|
||||
}
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
return ((ret == 0) ? CLI_SUCCESS : CLI_FAILURE);
|
||||
#else
|
||||
return ((ret == 0) ? RESULT_SUCCESS : RESULT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void diva_verbose_load(void)
|
||||
{
|
||||
divaDbgIfc = -1;
|
||||
open_diva_mnt();
|
||||
if (divaDbgIfc >= 0) {
|
||||
diva_verbose_start();
|
||||
}
|
||||
}
|
||||
|
||||
void diva_verbose_unload(void)
|
||||
{
|
||||
if (verbose_registered != 0) {
|
||||
verbose_registered = !(ast_unregister_verbose(diva_verbose_write) == 0);
|
||||
}
|
||||
if (verbose_registered != 0)
|
||||
cc_mutex_lock(&dbgIfcLock);
|
||||
if (divaDbgIfc >= 0) {
|
||||
close(divaDbgIfc);
|
||||
divaDbgIfc = -1;
|
||||
}
|
||||
if (verbose_registered != 0)
|
||||
cc_mutex_unlock(&dbgIfcLock);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic(R), 2011
|
||||
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
* \brief Declares interface to diva trace system
|
||||
*/
|
||||
#ifndef __DIVA_VERBOSER_H__
|
||||
#define __DIVA_VERBOSER_H__
|
||||
|
||||
#ifdef DIVA_VERBOSE
|
||||
|
||||
void diva_verbose_load(void);
|
||||
void diva_verbose_unload(void);
|
||||
|
||||
#ifdef CC_AST_HAS_VERSION_1_6
|
||||
char *pbxcli_capi_do_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
char *pbxcli_capi_no_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
|
||||
#else
|
||||
int pbxcli_capi_do_verbose(int fd, int argc, char *argv[]);
|
||||
int pbxcli_capi_no_verbose(int fd, int argc, char *argv[]);
|
||||
#endif
|
||||
|
||||
#define CC_CLI_TEXT_CAPI_DO_VERBOSE "Connect " CC_MESSAGE_BIGNAME " to debug driver"
|
||||
#define CC_CLI_TEXT_CAPI_NO_VERBOSE "Disconnect " CC_MESSAGE_BIGNAME " from debug driver"
|
||||
|
||||
|
||||
#ifndef CC_AST_HAS_VERSION_1_6
|
||||
extern char capi_do_verbose_usage[];
|
||||
extern char capi_no_verbose_usage[];
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define diva_verbose_load() do{}while(0)
|
||||
#define diva_verbose_unload() do{}while(0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic, 2009.
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Dialogic range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#include "dlist.h"
|
||||
|
||||
/*
|
||||
** Initialize linked list
|
||||
*/
|
||||
|
||||
void
|
||||
diva_q_init (diva_entity_queue_t* q)
|
||||
{
|
||||
q->head = q->tail = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove element from linked list
|
||||
*/
|
||||
void
|
||||
diva_q_remove (diva_entity_queue_t* q, diva_entity_link_t* what)
|
||||
{
|
||||
if(!what->prev) {
|
||||
if ((q->head = what->next)) {
|
||||
q->head->prev = 0;
|
||||
} else {
|
||||
q->tail = 0;
|
||||
}
|
||||
} else if (!what->next) {
|
||||
q->tail = what->prev;
|
||||
q->tail->next = 0;
|
||||
} else {
|
||||
what->prev->next = what->next;
|
||||
what->next->prev = what->prev;
|
||||
}
|
||||
what->prev = what->next = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add element to the tail of linked list
|
||||
*/
|
||||
void
|
||||
diva_q_add_tail (diva_entity_queue_t* q, diva_entity_link_t* what)
|
||||
{
|
||||
what->next = 0;
|
||||
if (!q->head) {
|
||||
what->prev = 0;
|
||||
q->head = q->tail = what;
|
||||
} else {
|
||||
what->prev = q->tail;
|
||||
q->tail->next = what;
|
||||
q->tail = what;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add element to the linked list after a specified element
|
||||
*/
|
||||
void diva_q_insert_after (diva_entity_queue_t* q, diva_entity_link_t* prev, diva_entity_link_t* what)
|
||||
{
|
||||
diva_entity_link_t *next;
|
||||
|
||||
if((0 == prev) || (0 == (next=diva_q_get_next(prev)))){
|
||||
diva_q_add_tail(q,what);
|
||||
return;
|
||||
}
|
||||
what->prev = prev;
|
||||
what->next = next;
|
||||
prev->next = what;
|
||||
next->prev = what;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add element to the linked list before a specified element
|
||||
*/
|
||||
void diva_q_insert_before (diva_entity_queue_t* q, diva_entity_link_t* next, diva_entity_link_t* what)
|
||||
{
|
||||
diva_entity_link_t *prev;
|
||||
|
||||
if(!next){
|
||||
diva_q_add_tail(q,what);
|
||||
return;
|
||||
}
|
||||
if(0 == (prev=diva_q_get_prev(next))){/*next seems to be the head*/
|
||||
q->head=what;
|
||||
what->prev=0;
|
||||
what->next=next;
|
||||
next->prev=what;
|
||||
}else{ /*not the head*/
|
||||
what->prev = prev;
|
||||
what->next = next;
|
||||
prev->next = what;
|
||||
next->prev = what;
|
||||
}
|
||||
}
|
||||
|
||||
diva_entity_link_t* diva_q_find (const diva_entity_queue_t* q, const void* what,
|
||||
diva_q_cmp_fn_t cmp_fn)
|
||||
{
|
||||
diva_entity_link_t* diva_q_current = q->head;
|
||||
|
||||
while (diva_q_current) {
|
||||
if (!(*cmp_fn)(what, diva_q_current)) {
|
||||
break;
|
||||
}
|
||||
diva_q_current = diva_q_current->next;
|
||||
}
|
||||
|
||||
return (diva_q_current);
|
||||
}
|
||||
|
||||
diva_entity_link_t*
|
||||
diva_q_get_head (const diva_entity_queue_t* q)
|
||||
{
|
||||
return (q->head);
|
||||
}
|
||||
|
||||
diva_entity_link_t*
|
||||
diva_q_get_tail (const diva_entity_queue_t* q)
|
||||
{
|
||||
return (q->tail);
|
||||
}
|
||||
|
||||
diva_entity_link_t*
|
||||
diva_q_get_next (const diva_entity_link_t* what)
|
||||
{
|
||||
return ((what) ? what->next : 0);
|
||||
}
|
||||
|
||||
diva_entity_link_t*
|
||||
diva_q_get_prev (const diva_entity_link_t* what)
|
||||
{
|
||||
return ((what) ? what->prev : 0);
|
||||
}
|
||||
|
||||
int
|
||||
diva_q_get_nr_of_entries (const diva_entity_queue_t* q)
|
||||
{
|
||||
int i = 0;
|
||||
const diva_entity_link_t* diva_q_current = q->head;
|
||||
|
||||
while (diva_q_current) {
|
||||
i++;
|
||||
diva_q_current = diva_q_current->next;
|
||||
}
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
*
|
||||
Copyright (c) Dialogic, 2009.
|
||||
*
|
||||
This source file is supplied for the use with
|
||||
Dialogic range of DIVA Server Adapters.
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
*
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
*
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __DIVA_LINK_H__
|
||||
#define __DIVA_LINK_H__
|
||||
|
||||
struct _diva_entity_link;
|
||||
typedef struct _diva_entity_link {
|
||||
struct _diva_entity_link* prev;
|
||||
struct _diva_entity_link* next;
|
||||
} diva_entity_link_t;
|
||||
|
||||
typedef struct _diva_entity_queue {
|
||||
diva_entity_link_t* head;
|
||||
diva_entity_link_t* tail;
|
||||
} diva_entity_queue_t;
|
||||
|
||||
typedef int (*diva_q_cmp_fn_t)(const void* what,
|
||||
const diva_entity_link_t*);
|
||||
|
||||
void diva_q_remove (diva_entity_queue_t* q, diva_entity_link_t* what);
|
||||
void diva_q_add_tail (diva_entity_queue_t* q, diva_entity_link_t* what);
|
||||
void diva_q_insert_after (diva_entity_queue_t* q, diva_entity_link_t* prev, diva_entity_link_t* what);
|
||||
void diva_q_insert_before (diva_entity_queue_t* q, diva_entity_link_t* next, diva_entity_link_t* what);
|
||||
diva_entity_link_t* diva_q_find (const diva_entity_queue_t* q,
|
||||
const void* what, diva_q_cmp_fn_t cmp_fn);
|
||||
|
||||
diva_entity_link_t* diva_q_get_head (const diva_entity_queue_t* q);
|
||||
diva_entity_link_t* diva_q_get_tail (const diva_entity_queue_t* q);
|
||||
diva_entity_link_t* diva_q_get_next (const diva_entity_link_t* what);
|
||||
diva_entity_link_t* diva_q_get_prev (const diva_entity_link_t* what);
|
||||
int diva_q_get_nr_of_entries (const diva_entity_queue_t* q);
|
||||
void diva_q_init (diva_entity_queue_t* q);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,341 @@
|
|||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,38 @@
|
|||
This Library supports remote CAPI over an TCP/IP network.
|
||||
|
||||
On the remote machine you need to have running
|
||||
kernelcapi
|
||||
libcapi20
|
||||
rcapid
|
||||
|
||||
On the local machine you just need this libcapi20 and
|
||||
your application.
|
||||
|
||||
For remote configuration the library looks for
|
||||
~/.capi20rc
|
||||
and if it doesn't exist it looks for
|
||||
/etc/capi20.conf
|
||||
|
||||
To set the remote machine, the above file need to have
|
||||
the following line
|
||||
REMOTE <remote hostname|ip-address> <remote port>
|
||||
|
||||
If this doesn't exist, the library tries the old, normal way
|
||||
of using the local /dev/capi20.
|
||||
|
||||
|
||||
Trace-Feature:
|
||||
If the CAPI messages shall be logged, add the following entries to
|
||||
the configuration file:
|
||||
TRACEFILE </path/to/tracefile>
|
||||
TRACELEVEL 0|1|2
|
||||
|
||||
The tracelevel configured which CAPI messages shall be logged:
|
||||
0 = none
|
||||
1 = signaling messages
|
||||
2 = all (including data messages)
|
||||
|
||||
---
|
||||
Armin Schindler
|
||||
armin@melware.de
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* CAPI 2.0 library
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*
|
||||
*/
|
||||
#ifndef __CAPI20_H__
|
||||
#define __CAPI20_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* standard CAPI2.0 functions */
|
||||
|
||||
unsigned capi20_register (
|
||||
unsigned MaxLogicalConnection,
|
||||
unsigned MaxBDataBlocks,
|
||||
unsigned MaxBDataLen,
|
||||
unsigned *ApplIDp);
|
||||
|
||||
unsigned capi20_release (unsigned ApplID);
|
||||
|
||||
unsigned capi20_put_message (unsigned ApplID, unsigned char *Msg);
|
||||
|
||||
unsigned capi20_get_message (unsigned ApplID, unsigned char **Buf);
|
||||
|
||||
unsigned capi20_waitformessage(unsigned ApplID, struct timeval *TimeOut);
|
||||
|
||||
unsigned char *capi20_get_manufacturer (unsigned Ctrl, unsigned char *Buf);
|
||||
|
||||
unsigned char *capi20_get_version (unsigned Ctrl, unsigned char *Buf);
|
||||
|
||||
unsigned char *capi20_get_serial_number (unsigned Ctrl, unsigned char *Buf);
|
||||
|
||||
unsigned capi20_get_profile (unsigned Controller, unsigned char *Buf);
|
||||
|
||||
unsigned capi20_isinstalled (void);
|
||||
|
||||
int capi20_fileno(unsigned ApplID);
|
||||
|
||||
/* end standard CAPI2.0 functions */
|
||||
|
||||
/* extentions functions (no standard functions) */
|
||||
|
||||
int capi20ext_get_flags(unsigned ApplID, unsigned *flagsptr);
|
||||
int capi20ext_set_flags(unsigned ApplID, unsigned flags);
|
||||
int capi20ext_clr_flags(unsigned ApplID, unsigned flags);
|
||||
|
||||
char *capi20ext_get_tty_devname(
|
||||
unsigned applid,
|
||||
unsigned ncci,
|
||||
char *buf,
|
||||
size_t size);
|
||||
|
||||
char *capi20ext_get_raw_devname(
|
||||
unsigned applid,
|
||||
unsigned ncci,
|
||||
char *buf,
|
||||
size_t size);
|
||||
|
||||
int capi20ext_ncci_opencount(unsigned applid, unsigned ncci);
|
||||
|
||||
/* end extentions functions (no standard functions) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __NO_CAPIUTILS__
|
||||
#include <capiutils.h>
|
||||
#endif
|
||||
|
||||
#endif /* __CAPI20_H */
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef __CAPI20_PLATFORM_H__
|
||||
#define __CAPI20_PLATFORM_H__
|
||||
|
||||
#if __GNUC__ >= 3 /* { */
|
||||
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
#else /* } { */
|
||||
|
||||
#ifndef likely
|
||||
#define likely(__x__) (!!(__x__))
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(__x__) (!!(__x__))
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
*
|
||||
* CAPI 2.0 Interface for Linux
|
||||
*
|
||||
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*
|
||||
*/
|
||||
#ifndef __CAPICMD_H__
|
||||
#define __CAPICMD_H__
|
||||
|
||||
#define CAPI_MSG_BASELEN 8
|
||||
#define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2)
|
||||
#define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2)
|
||||
|
||||
/*----- CAPI commands -----*/
|
||||
#define CAPI_ALERT 0x01
|
||||
#define CAPI_CONNECT 0x02
|
||||
#define CAPI_CONNECT_ACTIVE 0x03
|
||||
#define CAPI_CONNECT_B3_ACTIVE 0x83
|
||||
#define CAPI_CONNECT_B3 0x82
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
|
||||
#define CAPI_DATA_B3 0x86
|
||||
#define CAPI_DISCONNECT_B3 0x84
|
||||
#define CAPI_DISCONNECT 0x04
|
||||
#define CAPI_FACILITY 0x80
|
||||
#define CAPI_INFO 0x08
|
||||
#define CAPI_LISTEN 0x05
|
||||
#define CAPI_MANUFACTURER 0xff
|
||||
#define CAPI_RESET_B3 0x87
|
||||
#define CAPI_SELECT_B_PROTOCOL 0x41
|
||||
|
||||
/*----- CAPI subcommands -----*/
|
||||
|
||||
#define CAPI_REQ 0x80
|
||||
#define CAPI_CONF 0x81
|
||||
#define CAPI_IND 0x82
|
||||
#define CAPI_RESP 0x83
|
||||
|
||||
/*----- CAPI combined commands -----*/
|
||||
|
||||
#define CAPICMD(cmd,subcmd) (((cmd)<<8)|(subcmd))
|
||||
|
||||
#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
|
||||
#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
|
||||
#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
|
||||
#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
|
||||
#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
|
||||
#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
|
||||
|
||||
#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
|
||||
|
||||
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
|
||||
#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
|
||||
|
||||
#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
|
||||
#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
|
||||
#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
|
||||
#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
|
||||
#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
|
||||
#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
|
||||
#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
|
||||
#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
|
||||
#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
|
||||
#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
|
||||
|
||||
#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
|
||||
#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
|
||||
|
||||
#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
|
||||
#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
|
||||
#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
|
||||
#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
|
||||
|
||||
#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
|
||||
#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
|
||||
#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
|
||||
#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
|
||||
|
||||
#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
|
||||
#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
|
||||
#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
|
||||
#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
|
||||
|
||||
#endif /* __CAPICMD_H__ */
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
*
|
||||
* This program is free software and may be modified and
|
||||
* distributed under the terms of the GNU Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "capi20.h"
|
||||
|
||||
unsigned ALERT_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct BChannelinformation,
|
||||
_cstruct Keypadfacility,
|
||||
_cstruct Useruserdata,
|
||||
_cstruct Facilitydataarray
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
,_cstruct SendingComplete
|
||||
#endif
|
||||
) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x01,0x80,Messagenumber,adr);
|
||||
cmsg->BChannelinformation = BChannelinformation;
|
||||
cmsg->Keypadfacility = Keypadfacility;
|
||||
cmsg->Useruserdata = Useruserdata;
|
||||
cmsg->Facilitydataarray = Facilitydataarray;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->SendingComplete = SendingComplete;
|
||||
#endif
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword CIPValue,
|
||||
_cstruct CalledPartyNumber,
|
||||
_cstruct CallingPartyNumber,
|
||||
_cstruct CalledPartySubaddress,
|
||||
_cstruct CallingPartySubaddress,
|
||||
_cword B1protocol,
|
||||
_cword B2protocol,
|
||||
_cword B3protocol,
|
||||
_cstruct B1configuration,
|
||||
_cstruct B2configuration,
|
||||
_cstruct B3configuration,
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
_cstruct Globalconfiguration,
|
||||
#endif
|
||||
_cstruct BC,
|
||||
_cstruct LLC,
|
||||
_cstruct HLC,
|
||||
_cstruct BChannelinformation,
|
||||
_cstruct Keypadfacility,
|
||||
_cstruct Useruserdata,
|
||||
_cstruct Facilitydataarray
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
,_cstruct SendingComplete
|
||||
#endif
|
||||
) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x02,0x80,Messagenumber,adr);
|
||||
cmsg->CIPValue = CIPValue;
|
||||
cmsg->CalledPartyNumber = CalledPartyNumber;
|
||||
cmsg->CallingPartyNumber = CallingPartyNumber;
|
||||
cmsg->CalledPartySubaddress = CalledPartySubaddress;
|
||||
cmsg->CallingPartySubaddress = CallingPartySubaddress;
|
||||
cmsg->B1protocol = B1protocol;
|
||||
cmsg->B2protocol = B2protocol;
|
||||
cmsg->B3protocol = B3protocol;
|
||||
cmsg->B1configuration = B1configuration;
|
||||
cmsg->B2configuration = B2configuration;
|
||||
cmsg->B3configuration = B3configuration;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->Globalconfiguration = Globalconfiguration;
|
||||
#endif
|
||||
cmsg->BC = BC;
|
||||
cmsg->LLC = LLC;
|
||||
cmsg->HLC = HLC;
|
||||
cmsg->BChannelinformation = BChannelinformation;
|
||||
cmsg->Keypadfacility = Keypadfacility;
|
||||
cmsg->Useruserdata = Useruserdata;
|
||||
cmsg->Facilitydataarray = Facilitydataarray;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->SendingComplete = SendingComplete;
|
||||
#endif
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_B3_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct NCPI) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x82,0x80,Messagenumber,adr);
|
||||
cmsg->NCPI = NCPI;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DATA_B3_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
void *Data,
|
||||
_cword DataLength,
|
||||
_cword DataHandle,
|
||||
_cword Flags) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x86,0x80,Messagenumber,adr);
|
||||
cmsg->Data = Data;
|
||||
cmsg->DataLength = DataLength;
|
||||
cmsg->DataHandle = DataHandle;
|
||||
cmsg->Flags = Flags;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DISCONNECT_B3_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct NCPI) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x84,0x80,Messagenumber,adr);
|
||||
cmsg->NCPI = NCPI;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DISCONNECT_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct BChannelinformation,
|
||||
_cstruct Keypadfacility,
|
||||
_cstruct Useruserdata,
|
||||
_cstruct Facilitydataarray) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x04,0x80,Messagenumber,adr);
|
||||
cmsg->BChannelinformation = BChannelinformation;
|
||||
cmsg->Keypadfacility = Keypadfacility;
|
||||
cmsg->Useruserdata = Useruserdata;
|
||||
cmsg->Facilitydataarray = Facilitydataarray;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->SendingComplete = NULL;
|
||||
#endif
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned FACILITY_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword FacilitySelector,
|
||||
_cstruct FacilityRequestParameter) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x80,0x80,Messagenumber,adr);
|
||||
cmsg->FacilitySelector = FacilitySelector;
|
||||
cmsg->FacilityRequestParameter = FacilityRequestParameter;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned INFO_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct CalledPartyNumber,
|
||||
_cstruct BChannelinformation,
|
||||
_cstruct Keypadfacility,
|
||||
_cstruct Useruserdata,
|
||||
_cstruct Facilitydataarray
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
,_cstruct SendingComplete
|
||||
#endif
|
||||
) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x08,0x80,Messagenumber,adr);
|
||||
cmsg->CalledPartyNumber = CalledPartyNumber;
|
||||
cmsg->BChannelinformation = BChannelinformation;
|
||||
cmsg->Keypadfacility = Keypadfacility;
|
||||
cmsg->Useruserdata = Useruserdata;
|
||||
cmsg->Facilitydataarray = Facilitydataarray;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->SendingComplete = SendingComplete;
|
||||
#endif
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned LISTEN_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cdword InfoMask,
|
||||
_cdword CIPmask,
|
||||
_cdword CIPmask2,
|
||||
_cstruct CallingPartyNumber,
|
||||
_cstruct CallingPartySubaddress) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x05,0x80,Messagenumber,adr);
|
||||
cmsg->InfoMask = InfoMask;
|
||||
cmsg->CIPmask = CIPmask;
|
||||
cmsg->CIPmask2 = CIPmask2;
|
||||
cmsg->CallingPartyNumber = CallingPartyNumber;
|
||||
cmsg->CallingPartySubaddress = CallingPartySubaddress;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned MANUFACTURER_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cdword ManuID,
|
||||
_cdword Class,
|
||||
_cdword Function,
|
||||
_cstruct ManuData) {
|
||||
capi_cmsg_header (cmsg,ApplId,0xff,0x80,Messagenumber,adr);
|
||||
cmsg->ManuID = ManuID;
|
||||
cmsg->Class = Class;
|
||||
cmsg->Function = Function;
|
||||
cmsg->ManuData = ManuData;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned RESET_B3_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cstruct NCPI) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x87,0x80,Messagenumber,adr);
|
||||
cmsg->NCPI = NCPI;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned SELECT_B_PROTOCOL_REQ (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword B1protocol,
|
||||
_cword B2protocol,
|
||||
_cword B3protocol,
|
||||
_cstruct B1configuration,
|
||||
_cstruct B2configuration,
|
||||
_cstruct B3configuration
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
,_cstruct Globalconfiguration
|
||||
#endif
|
||||
) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x41,0x80,Messagenumber,adr);
|
||||
cmsg->B1protocol = B1protocol;
|
||||
cmsg->B2protocol = B2protocol;
|
||||
cmsg->B3protocol = B3protocol;
|
||||
cmsg->B1configuration = B1configuration;
|
||||
cmsg->B2configuration = B2configuration;
|
||||
cmsg->B3configuration = B3configuration;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->Globalconfiguration = Globalconfiguration;
|
||||
#endif
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword Reject,
|
||||
_cword B1protocol,
|
||||
_cword B2protocol,
|
||||
_cword B3protocol,
|
||||
_cstruct B1configuration,
|
||||
_cstruct B2configuration,
|
||||
_cstruct B3configuration,
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
_cstruct Globalconfiguration,
|
||||
#endif
|
||||
_cstruct ConnectedNumber,
|
||||
_cstruct ConnectedSubaddress,
|
||||
_cstruct LLC,
|
||||
_cstruct BChannelinformation,
|
||||
_cstruct Keypadfacility,
|
||||
_cstruct Useruserdata,
|
||||
_cstruct Facilitydataarray) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x02,0x83,Messagenumber,adr);
|
||||
cmsg->Reject = Reject;
|
||||
cmsg->B1protocol = B1protocol;
|
||||
cmsg->B2protocol = B2protocol;
|
||||
cmsg->B3protocol = B3protocol;
|
||||
cmsg->B1configuration = B1configuration;
|
||||
cmsg->B2configuration = B2configuration;
|
||||
cmsg->B3configuration = B3configuration;
|
||||
#ifndef CAPI_LIBRARY_V2
|
||||
cmsg->Globalconfiguration = Globalconfiguration;
|
||||
#endif
|
||||
cmsg->ConnectedNumber = ConnectedNumber;
|
||||
cmsg->ConnectedSubaddress = ConnectedSubaddress;
|
||||
cmsg->LLC = LLC;
|
||||
cmsg->BChannelinformation = BChannelinformation;
|
||||
cmsg->Keypadfacility = Keypadfacility;
|
||||
cmsg->Useruserdata = Useruserdata;
|
||||
cmsg->Facilitydataarray = Facilitydataarray;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_ACTIVE_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x03,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_B3_ACTIVE_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x83,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_B3_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword Reject,
|
||||
_cstruct NCPI) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x82,0x83,Messagenumber,adr);
|
||||
cmsg->Reject = Reject;
|
||||
cmsg->NCPI = NCPI;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned CONNECT_B3_T90_ACTIVE_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x88,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DATA_B3_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword DataHandle) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x86,0x83,Messagenumber,adr);
|
||||
cmsg->DataHandle = DataHandle;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DISCONNECT_B3_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x84,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned DISCONNECT_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x04,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned FACILITY_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cword FacilitySelector,
|
||||
_cstruct FacilityResponseParameters) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x80,0x83,Messagenumber,adr);
|
||||
cmsg->FacilitySelector = FacilitySelector;
|
||||
cmsg->FacilityResponseParameters = FacilityResponseParameters;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned INFO_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x08,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned MANUFACTURER_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr,
|
||||
_cdword ManuID,
|
||||
_cdword Class,
|
||||
_cdword Function,
|
||||
_cstruct ManuData) {
|
||||
capi_cmsg_header (cmsg,ApplId,0xff,0x83,Messagenumber,adr);
|
||||
cmsg->ManuID = ManuID;
|
||||
cmsg->Class = Class;
|
||||
cmsg->Function = Function;
|
||||
cmsg->ManuData = ManuData;
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
||||
|
||||
unsigned RESET_B3_RESP (_cmsg *cmsg, _cword ApplId, _cword Messagenumber,
|
||||
_cdword adr) {
|
||||
capi_cmsg_header (cmsg,ApplId,0x87,0x83,Messagenumber,adr);
|
||||
return capi_put_cmsg (cmsg);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue