NSF.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:22k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: NSF.c++,v 1.11 2009/07/02 05:16:20 faxguy Exp $ */
  2. /* 
  3.  * This file does not exist in the original HylaFAX distribution.
  4.  * Created by Dmitry Bely, April 2000
  5.  */
  6. /*
  7.  * Copyright (c) 1994-1996 Sam Leffler
  8.  * Copyright (c) 1994-1996 Silicon Graphics, Inc.
  9.  * HylaFAX is a trademark of Silicon Graphics
  10.  *
  11.  * Permission to use, copy, modify, distribute, and sell this software and 
  12.  * its documentation for any purpose is hereby granted without fee, provided
  13.  * that (i) the above copyright notices and this permission notice appear in
  14.  * all copies of the software and related documentation, and (ii) the names of
  15.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  16.  * publicity relating to the software without the specific, prior written
  17.  * permission of Sam Leffler and Silicon Graphics.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  20.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  21.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  22.  * 
  23.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  24.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  25.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  26.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  27.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  28.  * OF THIS SOFTWARE.
  29.  */
  30. #include <ctype.h>
  31. #include "NSF.h"
  32. struct ModelData 
  33. {
  34.     const char* modelId;
  35.     const char* modelName;
  36. };
  37. struct NSFData {
  38.     const char* vendorId;
  39.     u_int       vendorIdSize; // Country & provider code (T.35)
  40.     const char* vendorName;
  41.     bool        inverseStationIdOrder;
  42.     u_int         modelIdPos;
  43.     u_int         modelIdSize;
  44.     const ModelData* knownModels;
  45. };
  46. /*
  47.  * Unless a manufacturer is able to provide detailed specifics
  48.  * of the construction of their NSF signals the only guaranteed
  49.  * accurate information that we get from NSF is the manufacturer
  50.  * (once the bitorder and construction of the first few bytes is
  51.  * confirmed).  At that point we would ideally be able to identify
  52.  * the model type, but doing that is often more guesswork than
  53.  * anything and is more likely to prove wrong than right, depending
  54.  * on how specific our ModelData typing is.  Any matches as to the
  55.  * model identification really should be taken with some degree
  56.  * of scepticism.
  57.  *
  58.  * As manufacturers often encode (in plain text) a station identification
  59.  * in the NSF string it is often useful to look for that.
  60.  */
  61. static const ModelData Canon[] =
  62. {{"x80x00x80x48x00", "Faxphone B640"},
  63.  {"x80x00x80x49x10", "Fax B100"},
  64.  {"x80x00x8Ax49x10", "Laser Class 9000 Series"},
  65.  {"x80x00x8Ax48x00", "Laser Class 2060"},
  66.  {NULL}};
  67.   
  68. static const ModelData Brother[] =
  69. {{"x55x55x00x88x90x80x5Fx00x15x51", "Fax-560/770"},
  70.  {"x55x55x00x80xB0x80x00x00x59xD4", "Personal fax 190"},
  71.  {"x55x55x00x8Cx90x80", "MFC-3100C/MFC-8600"},
  72.  {NULL}};
  73. static const ModelData Panasonic0E[] =
  74. {{"x00x00x00x96x0Fx01x02x00x10x05x02x95xC8x08x01x49x02x41x53x54x47", "KX-F90" },
  75.  {"x00x00x00x96x0Fx01x03x00x10x05x02x95xC8x08x01x49x02x03", "KX-F230/KX-FT21" },
  76.  {"x00x00x00x16x0Fx01x03x00x10x05x02x95xC8x08",          "KX-F780" },
  77.  {"x00x00x00x16x0Fx01x03x00x10x00x02x95x80x08x75xB5",  "KX-M260" },
  78.  {"x00x00x00x16x0Fx01x02x00x10x05x02x85xC8x08xAD", "KX-F2050BS" },
  79.  {NULL}};
  80. static const ModelData Panasonic79[] =
  81. {{"x00x00x00x02x0Fx09x12x00x10x05x02x95xC8x88x80x80x01", "UF-S10" },
  82.  {"x00x00x00x16x7Fx09x13x00x10x05x16x8DxC0xD0xF8x80x01", "/Siemens Fax 940" },
  83.  {"x00x00x00x16x0Fx09x13x00x10x05x06x8DxC0x50xCB", "Panafax UF-321" },
  84.  {NULL}};
  85. static const ModelData Ricoh[] =
  86. {{"x00x00x00x12x10x0Dx02x00x50x00x2AxB8x2C", "/Nashuatec P394" },
  87.  {NULL}};
  88. static const ModelData Samsung16[] =
  89. {{"x00x00xA4x01", "M545 6800" },
  90.  {NULL}};
  91. static const ModelData Samsung8C[] =
  92. {{"x00x00x01x00", "SF-2010" },
  93.  {NULL}};
  94. static const ModelData SamsungA2[] =
  95. {{"x00x00x80x00", "FX-4000" },
  96.  {NULL}};
  97. static const ModelData Sanyo[] =
  98. {{"x00x00x10xB1x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04x04xFFxFFxFFxFFxFFxFFxFFxFFx41x26xFFxFFx00x00x85xA1", "SFX-107" },
  99.  {"x00x00x00xB1x12xF2x62xB4x82x0AxF2x2Ax12xD2xA2x04x04x04x04x04x04x04x04x04x04x04x04x04xFFxFFxFFxFFxFFxFFxFFxFFx41x4ExFFxFFx00x00", "MFP-510" },
  100.  {NULL}};
  101. static const ModelData HP[] =
  102. {{"x20x00x45x00x0Cx04x70xCDx4Fx00x7Fx49", "LaserJet 3150" },
  103.  {"x40x80x84x01xF0x6A", "OfficeJet" },
  104.  {"xC0x00x00x00x00", "OfficeJet 500" },
  105.  {"xC0x00x00x00x00x8B", "Fax-920" },
  106.  {NULL}};
  107. static const ModelData Sharp[] =
  108. {{"x00xCExB8x80x80x11x85x0DxDDx00x00xDDxDDx00x00xDDxDDx00x00x00x00x00x00x00x00xEDx22xB0x00x00x90x00x8C", "Sharp UX-460" },
  109.  {"x00x4ExB8x80x80x11x84x0DxDDx00x00xDDxDDx00x00xDDxDDx00x00x00x00x00x00x00x00xEDx22xB0x00x00x90x00xAD", "Sharp UX-177" },
  110.  {"x00xCExB8x00x84x0DxDDx00x00xDDxDDx00x00xDDxDDxDDxDDxDDx02x05x28x02x22x43x29xEDx23x90x00x00x90x01x00", "Sharp FO-4810" },
  111.  {NULL}};
  112. static const ModelData Xerox[] =
  113. {{"x00x08x2Dx43x57x50x61x75xFFxFFxFFxFFxFFxFFxFFx01x1Ax02x02x10x01x82x01x30x34", "635 Workcenter" },
  114.  {NULL}};
  115. static const ModelData XeroxDA[] =
  116. {{"x00x00xC0x00", "Workcentre Pro 580" },
  117.  {NULL}};
  118. static const ModelData Lexmark[] =
  119. {{"x00x80xA0x00", "X4270" },
  120.  {NULL}};
  121. static const ModelData JetFax[] =
  122. {{"x01x00x45x00x0Dx7F", "M910e" },
  123.  {NULL}};
  124. static const ModelData PitneyBowes[] = 
  125. {{"x79x91xB1xB8x7AxD8", "9550" },
  126.  {NULL}};
  127. static const ModelData Muratec45[] =
  128. {{"xF4x91xFFxFFxFFx42x2AxBCx01x57", "M4700" },
  129.  {NULL}};
  130. static const ModelData Muratec48[] =
  131. {{"x53x53x61", "M620" },
  132.  {NULL}};
  133. /*
  134.  * Country code first byte, then manufacturer is last two bytes. See T.35.
  135.  * Apparently Germany issued some manufacturer codes before the two-byte
  136.  * standard was accepted, and so some few German manufacturers are
  137.  * identified by a single manufacturer byte.
  138.  *
  139.  * T.30 5.3.6.2.7 (2003) states that the NSF FIF is transmitted
  140.  * in MSB2LSB order.  Revisions of T.30 prior to 2003 did not 
  141.  * contain explicit specification as to the transmit bit order.
  142.  * (Although it did otherwise state that all HDLC frame data should
  143.  * be in MSB order except as noted.)  Because CSI, TSI, and other
  144.  * prologue frames were in LSB order by way of an exception to the
  145.  * general rule (T.30 5.3.6.2.4-11) many manufacturers assumed that
  146.  * NSF should also be in LSB order.  Consequently there will be
  147.  * some country-code "masquerading" as a terminal may use the
  148.  * proper country-code, but with an inverted bit order.
  149.  *
  150.  * Thus, country code x61 (Korea) turns into x86 (Papua New Guinea),
  151.  * code xB5 (USA) turns into xAD (Tunisia), code x26 (China) turns
  152.  * into x64 (Lebanon), code x04 (Germany) turns into x20 (Canada), 
  153.  * and code x3D (France) turns into xBC (Vietnam).
  154.  *
  155.  * For the most part it should be safe to identify a manufacturer
  156.  * both with the MSB and LSB ordered bits, as the "masqueraded" country
  157.  * is likely to not be actively assigning T.35 manufacturer codes.
  158.  * However, some manufacturers (e.g. Microsoft) may use MSB for the
  159.  * country code and LSB for the rest of the NSF, and so basically this
  160.  * table must be verified and corrected against actual real-world
  161.  * results.
  162.  */
  163. static const NSFData KnownNSF[] =
  164. {
  165.     /* Japan */
  166.     {"x00x00x00", 3, "unknown - indeterminate", true },
  167.     {"x00x00x01", 3, "Anjitsu",  false },
  168.     {"x00x00x02", 3, "Nippon Telephone", false },
  169.     {"x00x00x05", 3, "Mitsuba Electric", false },
  170.     {"x00x00x06", 3, "Master Net", false },
  171.     {"x00x00x09", 3, "Xerox/Toshiba", true, 3, 10, Xerox },
  172.     {"x00x00x0A", 3, "Kokusai",   false },
  173.     {"x00x00x0D", 3, "Logic System International", false },
  174.     {"x00x00x0E", 3, "Panasonic", false, 3,10, Panasonic0E },
  175.     {"x00x00x11", 3, "Canon",     false, 3, 5, Canon },
  176.     {"x00x00x15", 3, "Toyotsushen Machinery", false },
  177.     {"x00x00x16", 3, "System House Mind", false },
  178.     {"x00x00x19", 3, "Xerox",     true  },
  179.     {"x00x00x1D", 3, "Hitachi Software", false },
  180.     {"x00x00x21", 3, "Oki Electric/Lanier", true },
  181.     {"x00x00x25", 3, "Ricoh",     true,  3,10, Ricoh },
  182.     {"x00x00x26", 3, "Konica",    false },
  183.     {"x00x00x29", 3, "Japan Wireless", false },
  184.     {"x00x00x2D", 3, "Sony",      false },
  185.     {"x00x00x31", 3, "Sharp/Olivetti", false, 3, 10, Sharp },
  186.     {"x00x00x35", 3, "Kogyu", false },
  187.     {"x00x00x36", 3, "Japan Telecom", false },
  188.     {"x00x00x3D", 3, "IBM Japan", false },
  189.     {"x00x00x39", 3, "Panasonic", false },
  190.     {"x00x00x41", 3, "Swasaki Communication", false },
  191.     {"x00x00x45", 3, "Muratec",   false, 3,10, Muratec45 },
  192.     {"x00x00x46", 3, "Pheonix",   false },
  193.     {"x00x00x48", 3, "Muratec",   false, 3,3, Muratec48 }, // not registered
  194.     {"x00x00x49", 3, "Japan Electric", false },
  195.     {"x00x00x4D", 3, "Okura Electric", false },
  196.     {"x00x00x51", 3, "Sanyo",     false, 3,10, Sanyo },
  197.     {"x00x00x55", 3, "unknown - Japan 55", false },
  198.     {"x00x00x56", 3, "Brother",   false, 3, 6, Brother },
  199.     {"x00x00x59", 3, "Fujitsu",   false },
  200.     {"x00x00x5D", 3, "Kuoni",     false },
  201.     {"x00x00x61", 3, "Casio",     false },
  202.     {"x00x00x65", 3, "Tateishi Electric", false },
  203.     {"x00x00x66", 3, "Utax/Mita", true  },
  204.     {"x00x00x69", 3, "Hitachi Production",   false },
  205.     {"x00x00x6D", 3, "Hitachi Telecom", false },
  206.     {"x00x00x71", 3, "Tamura Electric Works", false },
  207.     {"x00x00x75", 3, "Tokyo Electric Corp.", false },
  208.     {"x00x00x76", 3, "Advance",   false },
  209.     {"x00x00x79", 3, "Panasonic", false, 3,10, Panasonic79 },
  210.     {"x00x00x7D", 3, "Seiko",     false },
  211.     {"x00x08x00", 3, "Daiko",     false },
  212.     {"x00x10x00", 3, "Funai Electric", false },
  213.     {"x00x20x00", 3, "Eagle System", false },
  214.     {"x00x30x00", 3, "Nippon Business Systems", false },
  215.     {"x00x40x00", 3, "Comtron",   false },
  216.     {"x00x48x00", 3, "Cosmo Consulting", false },
  217.     {"x00x50x00", 3, "Orion Electric", false },
  218.     {"x00x60x00", 3, "Nagano Nippon", false },
  219.     {"x00x70x00", 3, "Kyocera",   false },
  220.     {"x00x80x00", 3, "Kanda Networks", false },
  221.     {"x00x88x00", 3, "Soft Front", false },
  222.     {"x00x90x00", 3, "Arctic",    false },
  223.     {"x00xA0x00", 3, "Nakushima", false },
  224.     {"x00xB0x00", 3, "Minolta", false },
  225.     {"x00xC0x00", 3, "Tohoku Pioneer", false },
  226.     {"x00xD0x00", 3, "USC",       false },
  227.     {"x00xE0x00", 3, "Hiboshi",   false },
  228.     {"x00xF0x00", 3, "Sumitomo Electric", false },
  229.     /* Germany */
  230.     {"x20x09",     2, "ITK Institut für Telekommunikation GmbH & Co KG", false },
  231.     {"x20x11",     2, "Dr. Neuhaus Mikroelektronik", false },
  232.     {"x20x21",     2, "ITO Communication", false },
  233.     {"x20x31",     2, "mbp Kommunikationssysteme GmbH", false },
  234.     {"x20x41",     2, "Siemens", false },
  235.     {"x20x42",     2, "Deutsche Telekom AG", false },
  236.     {"x20x51",     2, "mps Software", false },
  237.     {"x20x61",     2, "Hauni Elektronik", false },
  238.     {"x20x71",     2, "Digitronic computersysteme gmbh", false },
  239.     {"x20x81x00", 3, "Innovaphone GmbH", false },
  240.     {"x20x81x40", 3, "TEDAS Gesellschaft für Telekommunikations-, Daten- und Audiosysteme mbH", false },
  241.     {"x20x81x80", 3, "AVM Audiovisuelles Marketing und Computersysteme GmbH", false },
  242.     {"x20x81xC0", 3, "EICON Technology Research GmbH", false },
  243.     {"x20xB1",     2, "Schneider Rundfunkwerke AG", false },
  244.     {"x20xC2",     2, "Deutsche Telekom AG", false },
  245.     {"x20xD1",     2, "Ferrari electronik GmbH", false },
  246.     {"x20xF1",     2, "DeTeWe - Deutsche Telephonwerke AG & Co", false },
  247.     {"x20xFF",     2, "Germany Regional Code", false },
  248.     /* China */
  249.     {"x64x00x00", 3, "unknown - China 00 00", false },
  250.     {"x64x01x00", 3, "unknown - China 01 00", false },
  251.     {"x64x01x01", 3, "unknown - China 01 01", false },
  252.     {"x64x01x02", 3, "unknown - China 01 02", false },
  253.     /* France */
  254.     {"xBCx53x01", 3, "Minolta",   false },
  255.     /* Korea */
  256.     {"x61x00x7A", 3, "Xerox", false },
  257.     {"x86x00x02", 3, "unknown - Korea 02", false },
  258.     {"x86x00x06", 3, "unknown - Korea 06", false },
  259.     {"x86x00x08", 3, "unknown - Korea 08", false },
  260.     {"x86x00x0A", 3, "unknown - Korea 0A", false },
  261.     {"x86x00x0E", 3, "unknown - Korea 0E", false },
  262.     {"x86x00x10", 3, "Samsung",   false },
  263.     {"x86x00x11", 3, "unknown - Korea 11" },
  264.     {"x86x00x16", 3, "Samsung", false, 3, 4, Samsung16 },
  265.     {"x86x00x1A", 3, "unknown - Korea 1A", false },
  266.     {"x86x00x40", 3, "unknown - Korea 40", false },
  267.     {"x86x00x48", 3, "Samsung/Dell", false },
  268.     {"x86x00x52", 3, "Samsung", false },
  269.     {"x86x00x5A", 3, "Samsung", false },
  270.     {"x86x00x5E", 3, "Xerox", false },
  271.     {"x86x00x66", 3, "unknown - Korea 66", false },
  272.     {"x86x00x6E", 3, "unknown - Korea 6E", false },
  273.     {"x86x00x82", 3, "unknown - Korea 82", false },
  274.     {"x86x00x88", 3, "Ricoh", false },
  275.     {"x86x00x8A", 3, "unknown - Korea 8A", false },
  276.     {"x86x00x8C", 3, "Samsung", false, 3, 4, Samsung8C },
  277.     {"x86x00x92", 3, "unknown - Korea 92", false },
  278.     {"x86x00x98", 3, "Samsung",   false },
  279.     {"x86x00xA2", 3, "Samsung", false, 3, 4, SamsungA2 },
  280.     {"x86x00xA4", 3, "unknown - Korea A4", false },
  281.     {"x86x00xC2", 3, "Samsung", false },
  282.     {"x86x00xC9", 3, "unknown - Korea C9", false },
  283.     {"x86x00xCC", 3, "unknown - Korea CC", false },
  284.     {"x86x00xD2", 3, "unknown - Korea D2", false },
  285.     {"x86x00xDA", 3, "Xerox", false, 3, 4, XeroxDA },
  286.     {"x86x00xE2", 3, "unknown - Korea E2", false },
  287.     {"x86x00xEC", 3, "unknown - Korea EC", false },
  288.     {"x86x00xEE", 3, "unknown - Korea EE", false },
  289.     /* United Kingdom */
  290.     {"xB4x00xB0", 3, "DCE",       false },
  291.     {"xB4x00xB1", 3, "Hasler",    false },
  292.     {"xB4x00xB2", 3, "Interquad", false },
  293.     {"xB4x00xB3", 3, "Comwave",   false },
  294.     {"xB4x00xB4", 3, "Iconographic", false },
  295.     {"xB4x00xB5", 3, "Wordcraft", false },
  296.     {"xB4x00xB6", 3, "Acorn",     false },
  297.     /* United States */
  298.     {"xADx00x00", 3, "Pitney Bowes", false, 3, 6, PitneyBowes },
  299.     {"xADx00x0C", 3, "Dialogic",  false },
  300.     {"xADx00x15", 3, "Lexmark",   false, 3, 4, Lexmark },
  301.     {"xADx00x16", 3, "JetFax",    false, 3, 6, JetFax },
  302.     {"xADx00x24", 3, "Octel",     false },
  303.     {"xADx00x36", 3, "HP",        false, 3, 5, HP },
  304.     {"xADx00x42", 3, "FaxTalk",   false },
  305.     {"xADx00x44", 3, NULL,        true },
  306.     {"xADx00x46", 3, "BrookTrout", false },
  307.     {"xADx00x51", 3, "Telogy Networks", false },
  308.     {"xADx00x55", 3, "HylaFAX",   false },
  309.     {"xADx00x5C", 3, "IBM", false },
  310.     {"xADx00x98", 3, "unknown - USA 98", true },
  311.     {"xB5x00x01", 3, "Picturetel", false },
  312.     {"xB5x00x20", 3, "Conexant",  false },
  313.     {"xB5x00x22", 3, "Comsat",    false },
  314.     {"xB5x00x24", 3, "Octel",     false },
  315.     {"xB5x00x26", 3, "ROLM",      false },
  316.     {"xB5x00x28", 3, "SOFNET",    false },
  317.     {"xB5x00x29", 3, "TIA TR-29 Committee", false },
  318.     {"xB5x00x2A", 3, "STF Tech",  false },
  319.     {"xB5x00x2C", 3, "HKB",       false },
  320.     {"xB5x00x2E", 3, "Delrina",   false },
  321.     {"xB5x00x30", 3, "Dialogic",  false },
  322.     {"xB5x00x32", 3, "Applied Synergy", false },
  323.     {"xB5x00x34", 3, "Syncro Development", false },
  324.     {"xB5x00x36", 3, "Genoa",     false },
  325.     {"xB5x00x38", 3, "Texas Instruments", false },
  326.     {"xB5x00x3A", 3, "IBM",       false },
  327.     {"xB5x00x3C", 3, "ViaSat",    false },
  328.     {"xB5x00x3E", 3, "Ericsson",  false },
  329.     {"xB5x00x42", 3, "Bogosian",  false },
  330.     {"xB5x00x44", 3, "Adobe",     false },
  331.     {"xB5x00x46", 3, "Fremont Communications", false },
  332.     {"xB5x00x48", 3, "Hayes",     false },
  333.     {"xB5x00x4A", 3, "Lucent",    false },
  334.     {"xB5x00x4C", 3, "Data Race", false },
  335.     {"xB5x00x4E", 3, "TRW",       false },
  336.     {"xB5x00x52", 3, "Audiofax",  false },
  337.     {"xB5x00x54", 3, "Computer Automation", false },
  338.     {"xB5x00x56", 3, "Serca",     false },
  339.     {"xB5x00x58", 3, "Octocom",   false },
  340.     {"xB5x00x5C", 3, "Power Solutions", false },
  341.     {"xB5x00x5A", 3, "Digital Sound", false },
  342.     {"xB5x00x5E", 3, "Pacific Data", false },
  343.     {"xB5x00x60", 3, "Commetrex", false },
  344.     {"xB5x00x62", 3, "BrookTrout", false },
  345.     {"xB5x00x64", 3, "Gammalink", false },
  346.     {"xB5x00x66", 3, "Castelle",  false },
  347.     {"xB5x00x68", 3, "Hybrid Fax", false },
  348.     {"xB5x00x6A", 3, "Omnifax",   false },
  349.     {"xB5x00x6C", 3, "HP",        false },
  350.     {"xB5x00x6E", 3, "Microsoft", false },
  351.     {"xB5x00x72", 3, "Speaking Devices", false },
  352.     {"xB5x00x74", 3, "Compaq",    false },
  353. /*
  354.     {"xB5x00x76", 3, "Trust - Cryptek", false }, // collision with Microsoft
  355. */
  356.     {"xB5x00x76", 3, "Microsoft", false }, // uses LSB for country but MSB for manufacturer
  357.     {"xB5x00x78", 3, "Cylink",    false },
  358.     {"xB5x00x7A", 3, "Pitney Bowes", false },
  359.     {"xB5x00x7C", 3, "Digiboard", false },
  360.     {"xB5x00x7E", 3, "Codex",     false },
  361.     {"xB5x00x82", 3, "Wang Labs", false },
  362.     {"xB5x00x84", 3, "Netexpress Communications", false },
  363.     {"xB5x00x86", 3, "Cable-Sat", false },
  364.     {"xB5x00x88", 3, "MFPA",      false },
  365.     {"xB5x00x8A", 3, "Telogy Networks", false },
  366.     {"xB5x00x8E", 3, "Telecom Multimedia Systems", false },
  367.     {"xB5x00x8C", 3, "AT&T",      false },
  368.     {"xB5x00x92", 3, "Nuera",     false },
  369.     {"xB5x00x94", 3, "K56flex",   false },
  370.     {"xB5x00x96", 3, "MiBridge",  false },
  371.     {"xB5x00x98", 3, "Xerox",     false },
  372.     {"xB5x00x9A", 3, "Fujitsu",   false },
  373.     {"xB5x00x9B", 3, "Fujitsu",   false },
  374.     {"xB5x00x9C", 3, "Natural Microsystems",  false },
  375.     {"xB5x00x9E", 3, "CopyTele",  false },
  376.     {"xB5x00xA2", 3, "Murata",    false },
  377.     {"xB5x00xA4", 3, "Lanier",    false },
  378.     {"xB5x00xA6", 3, "Qualcomm",  false },
  379.     {"xB5x00xAA", 3, "HylaFAX",   false }, // we did it backwards for a while
  380.     {NULL}
  381. };
  382. NSF::NSF()
  383. {
  384.     clear();
  385. }
  386. NSF::NSF( const char* hexNSF, bool useHex )
  387. {
  388.     clear();
  389.     loadHexData( hexNSF, useHex );
  390.     decode();
  391. }
  392. NSF::NSF( const u_char* rawData, int size, const u_char* revTab )
  393. {
  394.     clear();
  395.     loadRawData( rawData, size, revTab );
  396.     decode();
  397. }
  398. void NSF::clear()
  399. {
  400.     nsf.resize(0);
  401.     hexNsf.resize(0);
  402.     vendor = "unknown";
  403.     model = "";
  404.     stationId = "";
  405.     vendorDecoded = false;
  406.     stationIdDecoded = false;
  407. }
  408. void NSF::loadHexData( const char* hexNSF, bool useHex )
  409. {
  410.     hexNsf.append( hexNSF );
  411.     const char *p = hexNSF;
  412.     char *pNext = NULL;
  413.     for( ;; ){
  414.         int val = strtol( p, &pNext, (useHex ? 16 : 10) );
  415.         if( pNext == p )
  416.             break;
  417.         p = pNext;
  418. if (p[0] != '') p++; // skip delimiter
  419.         nsf.append( (unsigned char)val );
  420.     }
  421. }
  422. void NSF::loadRawData( const u_char* rawData, int size, const u_char* revTab )
  423. {
  424.     nsf.append( (const char*)rawData, size );
  425.     u_char *p   = (u_char*)(const char*)nsf;
  426.     u_char *end = p+size;
  427.     for( ; p < end; p++ ){
  428.         *p = revTab[*p];
  429.         hexNsf.append(fxStr::format("%02X ", *p));
  430.     }
  431.     // remove trailing space
  432.     hexNsf.resize( hexNsf.length() - 1 );
  433. }
  434. void NSF::decode()
  435. {
  436.     u_int nsfSize = nsf.length();
  437.     for( const NSFData* p = KnownNSF; p->vendorId; p++ ){
  438.         if( nsfSize >= p->vendorIdSize &&
  439.             memcmp( p->vendorId, &nsf[0], p->vendorIdSize )==0 ){
  440.     if( p->vendorName )
  441.                 vendor = p->vendorName;
  442.             if( p->knownModels ){
  443.                 for( const ModelData* pp = p->knownModels; pp->modelId; pp++ )
  444.                     if( nsfSize >= p->modelIdPos + p->modelIdSize &&
  445.                         memcmp( pp->modelId, &nsf[p->modelIdPos], p->modelIdSize )==0 )
  446.                         model = pp->modelName;
  447.             }
  448.             findStationId( p->inverseStationIdOrder, p->vendorIdSize );
  449.             vendorDecoded = true;
  450.         }
  451.     }
  452.     if( !vendorFound() )
  453. findStationId( 0, 0 ); // don't skip initial bytes in search
  454. }
  455. void NSF::findStationId( bool reverseOrder, u_int vendorIdSize )
  456. {
  457.     const char* id = NULL;
  458.     u_int       idSize = 0;
  459.     const char* maxId = NULL;
  460.     u_int       maxIdSize = 0;
  461.     /*
  462.      * Sometimes station ID is in MSB2LSB, and sometimes it is in
  463.      * LSB2MSB. Rather than trying to collect bit order information
  464.      * about every fax machine out there, we simply inverse the
  465.      * data bit order and append it to the raw data and thereby
  466.      * check both ways.
  467.      */
  468.     fxStr thisnsf = nsf;
  469.     thisnsf.append((char) 0x00); // establish a break
  470.     for ( u_int i = 0 ; i < nsf.length(); i++ ) {
  471. // a one-byte bit-order converter...
  472. thisnsf.append((((nsf[i]>>0)&1)<<7)|(((nsf[i]>>1)&1)<<6)|
  473.       (((nsf[i]>>2)&1)<<5)|(((nsf[i]>>3)&1)<<4)|
  474.       (((nsf[i]>>4)&1)<<3)|(((nsf[i]>>5)&1)<<2)|
  475.       (((nsf[i]>>6)&1)<<1)|(((nsf[i]>>7)&1)<<0));
  476.     }
  477.     /*
  478.      * Trying to find the longest printable ASCII sequence
  479.      */
  480.     const char *p = (const char*) thisnsf, *end = p + thisnsf.length();
  481.     for (p += vendorIdSize; p < end; p++) {
  482.         if( isprint(*p) ){
  483.             if( !idSize++ ) 
  484.                 id = p;
  485.             if( idSize > maxIdSize ){
  486.                 maxId = id;
  487.                 maxIdSize = idSize;
  488.             }
  489.         }
  490.         else {
  491.             id = NULL;
  492.             idSize = 0;
  493.         }
  494.     }
  495.     
  496.     /*
  497.      * Minimum acceptable id length
  498.      */
  499.     const u_int MinIdSize = 4;
  500.     if( maxIdSize >= MinIdSize ){
  501.         stationId.resize(0);
  502.         const char* p;
  503.         int dir;
  504.         if( reverseOrder ){
  505.             p   = maxId + maxIdSize - 1;
  506.             dir = -1;
  507.         }
  508.         else {
  509.             p   = maxId;
  510.             dir = 1;
  511.         }
  512.         for( u_int i = 0; i < maxIdSize; i++ ){
  513.             stationId.append( *p );
  514.             p += dir;
  515.         }
  516.         stationIdDecoded = true;
  517.     }
  518. }