コード例 #1
0
        public override void Start()
        {
            // adapterSelected ranges from 1 thru number Of Adapters.  However, we need an 'index', which
            // is adapterSelected-1.
            int adapterIndex = MainForm.adapterSelected - 1;

            // get the name of this PC and, using it, the IP address of the first adapter
            IPAddress[] addr = Dns.GetHostEntry(strHostName).AddressList;

            MainForm.GetNetworkInterfaces();

            List <IPAddress> addrList = new List <IPAddress>();

            // make a list of all the adapters that we found in Dns.GetHostEntry(strHostName).AddressList
            foreach (IPAddress a in addr)
            {
                // make sure to get only IPV4 addresses!
                // test added because Erik Anderson noted an issue on Windows 7.  May have been in the socket
                // construction or binding below.
                if (a.AddressFamily == AddressFamily.InterNetwork)
                {
                    addrList.Add(a);
                }
            }

            bool foundMetis = false;
            List <MetisHermesDevice> mhd = new List <MetisHermesDevice>();

            if (MainForm.DoFastEthernetConnect && (MainForm.EthernetHostIPAddress.Length > 0) && (MainForm.Metis_IP_address.Length > 0))
            {
                // if success set foundMetis to true, and fill in ONE mhd entry.
                IPAddress targetIP;
                IPAddress hostIP;
                if (IPAddress.TryParse(MainForm.EthernetHostIPAddress, out hostIP) && IPAddress.TryParse(MainForm.Metis_IP_address, out targetIP))
                {
                    Console.WriteLine(String.Format("Attempting fast re-connect to host adapter {0}, metis IP {1}", MainForm.EthernetHostIPAddress, MainForm.Metis_IP_address));

                    if (DiscoverMetisOnPort(ref mhd, hostIP, targetIP))
                    {
                        foundMetis = true;

                        // make sure that there is only one entry in the list!
                        if (mhd.Count > 0)
                        {
                            // remove the extra ones that don't match!
                            MetisHermesDevice m2 = null;
                            foreach (var m in mhd)
                            {
                                if (m.IPAddress.CompareTo(MainForm.Metis_IP_address) == 0)
                                {
                                    m2 = m;
                                }
                            }

                            // clear the list and put our single element in it, if we found it.
                            mhd.Clear();
                            if (m2 != null)
                            {
                                mhd.Add(m2);
                            }
                            else
                            {
                                foundMetis = false;
                            }
                        }
                    }
                }
            }

            if (!foundMetis)
            {
                foreach (IPAddress ipa in addrList)
                {
                    if (DiscoverMetisOnPort(ref mhd, ipa, null))
                    {
                        foundMetis = true;
                    }
                }
            }

            if (!foundMetis)
            {
                MessageBox.Show("No Metis/Hermes board found  - Check HPSDR is connected and powered");
                MainForm.OnOffButton_Click(this, EventArgs.Empty); // Toggle ON/OFF Button to OFF
                return;
            }
            int chosenDevice = 0;

            if (mhd.Count > 1)
            {
                // show selection dialog.
                DeviceChooserForm dcf = new DeviceChooserForm(mhd, MainForm.MetisMAC);
                DialogResult      dr  = dcf.ShowDialog();
                if (dr == DialogResult.Cancel)
                {
                    MainForm.OnOffButton_Click(this, EventArgs.Empty); // Toggle ON/OFF Button to OFF
                    return;
                }

                chosenDevice = dcf.GetChosenItem();
            }

            MainForm.Metis_IP_address      = mhd[chosenDevice].IPAddress;
            MainForm.MetisMAC              = mhd[chosenDevice].MACAddress;
            MainForm.EthernetHostIPAddress = mhd[chosenDevice].hostPortIPAddress.ToString();

            iep = new IPEndPoint(mhd[chosenDevice].hostPortIPAddress, LocalPort);

            // bind (open) the socket so we can use the Metis/Hermes that was found/selected
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.Bind(iep);

            //TODO: look at the next line and consider when a larger buffer might be required, such as SpectrumSize > 192k
            socket.ReceiveBufferSize = 0x00040000;   // no lost frame counts at 192kHz with this setting
            socket.SendBufferSize    = 1032;
            socket.Blocking          = true;

            // create an endpoint for sending to Metis
            MetisEP = new IPEndPoint(IPAddress.Parse(MainForm.Metis_IP_address), MetisPort);

            IPEndPoint localEndPoint2 = (IPEndPoint)socket.LocalEndPoint;

            Console.WriteLine("Starting Ethernet Thread: host adapter IP {0}, port {1}", localEndPoint2.Address, localEndPoint2.Port);

            //// start thread to read Metis data from Ethernet.   DataLoop merely calls Process_Data,
            //// which calls usb_bulk_read() and rcvr.Process(),
            //// and stuffs the demodulated audio into AudioRing buffer
            loop_count           = 0; // reset count so that data will be re-collected
            Data_thread          = new Thread(new ThreadStart(DataLoop));
            Data_thread.Name     = "Ethernet Loop";
            Data_thread.Priority = ThreadPriority.Highest; // run USB thread at high priority
            Console.WriteLine("Ethernet Thread ID {0}", Data_thread.ManagedThreadId);
            Data_thread.Start();
            Data_thread_running = true;

            Data_send(true); // send a frame to Ozy to prime the pump
            Thread.Sleep(20);
            Data_send(true); // send a frame to Ozy to prime the pump,with freq this time

            // reset the sequence_number to match what Metis does following a Discovery
            sequence_number      = 0;
            last_sequence_number = 0xFFFFFFFF;
            //Spectrum_sequ_number = 0;
            last_spectrum_sequence_number = 0xFFFFFFFF;

            // start data from Metis
            Metis_start_stop(MainForm.Metis_IP_address, 0x03); // bit 0 is EP6 (normal data), bit 1 is EP4 (wide spectrum)

            MainForm.timer1.Enabled = true;                    // start timer for bandscope update etc.

            MainForm.timer2.Enabled  = true;                   // used by Clip LED, fires every 100mS
            MainForm.timer2.Interval = 100;
            MainForm.timer3.Enabled  = true;                   // used by VOX, fires on user VOX delay setting
            MainForm.timer3.Interval = 400;
            MainForm.timer4.Enabled  = true;                   // used by noise gate, fires on Gate delay setting
            MainForm.timer4.Interval = 100;

            // update the display on the SetupForm if it is being displayed
            if (MainForm.Setup_form != null)
            {
                MainForm.Setup_form.UpdateEthernetInfo();
            }
        }
コード例 #2
0
        /*
         * Broadcast a Metis Discovery packet and look for boards.
         *
         * Code Broadcasts (IP address FF.FF.FF.FF, the 'all broadcast address') a  UDP/IP PC HPSDR discovery packet on port 1024 with the following format:
         *
         *    0xEFFE, 0x02, <sixty bytes of zero>
         *
         * It then listens on the PC *from* port for a Metis reply with the following format:
         *
         *    0xEFFE, 0x02, Metis MAC address <41 bytes of zero>
         *
         * Metis' IP address is obtained from the packet header.
         *
         */

        private bool Metis_Discovery(ref List <MetisHermesDevice> mhdList, IPEndPoint iep, IPAddress targetIP)
        {
            string MetisMAC;

            socket.SendBufferSize = 1024;

            // set up HPSDR Metis discovery packet
            byte[] Metis_discovery = new byte[63];
            Array.Clear(Metis_discovery, 0, Metis_discovery.Length);

            byte[] Metis_discovery_preamble = new byte[] { 0xEF, 0xFE, 0x02 };
            Metis_discovery_preamble.CopyTo(Metis_discovery, 0);

            bool have_Metis = false;            // true when we find an Metis
            int  time_out   = 0;

            // set socket option so that broadcast is allowed.
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);

            // need this so we can Broadcast on the socket
            IPEndPoint broadcast  = new IPEndPoint(IPAddress.Broadcast, MetisPort);
            string     receivedIP = ""; // the IP address Metis obtains; assigned, from DHCP or APIPA (169.254.x.y)

            IPAddress hostPortIPAddress = iep.Address;
            IPAddress hostPortMask      = IPAddress.Broadcast;

            // find the subnet mask that goes with this host port
            foreach (NicProperties n in MainForm.nicProperties)
            {
                if (hostPortIPAddress.Equals(n.ipv4Address))
                {
                    hostPortMask = n.ipv4Mask;
                    break;
                }
            }

            // send every second until we either find an Metis board or exceed the number of attempts
            while (!have_Metis)            // #### djm should loop for a while in case there are multiple Metis boards
            {
                // send a broadcast to the port 1024
                socket.SendTo(Metis_discovery, broadcast);

                // now listen on  send port for any Metis cards
                Console.WriteLine("Ready to receive.... ");
                int    recv;
                byte[] data = new byte[100];

                bool data_available;

                // await possibly multiple replies, if there are multiple Metis/Hermes on this port,
                // which MIGHT be the 'any' port, 0.0.0.0
                do
                {
                    // Poll the port to see if data is available
                    data_available = socket.Poll(100000, SelectMode.SelectRead);  // wait 100 msec  for time out

                    if (data_available)
                    {
                        EndPoint remoteEP = new IPEndPoint(IPAddress.None, 0);
                        recv = socket.ReceiveFrom(data, ref remoteEP);                 // recv has number of bytes we received
                        //string stringData = Encoding.ASCII.GetString(data, 0, recv); // use this to print the received data

                        Console.WriteLine("raw Discovery data = " + BitConverter.ToString(data, 0, recv));

                        // get Metis MAC address from the payload
                        byte[] MAC = { 0, 0, 0, 0, 0, 0 };
                        Array.Copy(data, 3, MAC, 0, 6);
                        MetisMAC = BitConverter.ToString(MAC);
                        byte codeVersion = data[9];
                        byte boardType   = data[10];

                        // check for HPSDR frame ID and type 2 (not currently streaming data, which also means 'not yet in use')
                        // changed to find Metis boards, even if alreay in use!  This prevents the need to power-cycle metis.
                        // (G Byrkit, 8 Jan 2012)
                        if ((data[0] == 0xEF) && (data[1] == 0xFE) && ((data[2] & 0x02) != 0))
                        {
                            Console.WriteLine("\nFound a Metis/Hermes/Griffin.  Checking whether it qualifies");

                            // get Metis IP address from the IPEndPoint passed to ReceiveFrom.
                            IPEndPoint ripep          = (IPEndPoint)remoteEP;
                            IPAddress  receivedIPAddr = ripep.Address;
                            receivedIP = receivedIPAddr.ToString();

                            Console.WriteLine("Metis IP from IP Header = " + receivedIP);
                            Console.WriteLine("Metis MAC address from payload = " + MetisMAC);
                            if (!SameSubnet(receivedIPAddr, hostPortIPAddress, hostPortMask))
                            {
                                // device is NOT on the subnet that this port actually services.  Do NOT add to list!
                                Console.WriteLine("Not on subnet of host adapter! Adapter IP {0}, Adapter mask {1}",
                                                  hostPortIPAddress.ToString(), hostPortMask.ToString());
                            }
                            else if (receivedIPAddr.Equals(hostPortIPAddress))
                            {
                                Console.WriteLine("Rejected: contains same IP address as the host adapter; not from a Metis/Hermes/Griffin");
                            }
                            else if (MetisMAC.Equals("00-00-00-00-00-00"))
                            {
                                Console.WriteLine("Rejected: contains bogus MAC address of all-zeroes");
                            }
                            else
                            {
                                MetisHermesDevice mhd = new MetisHermesDevice();
                                mhd.IPAddress         = receivedIP;
                                mhd.MACAddress        = MetisMAC;
                                mhd.deviceType        = (DeviceType)boardType;
                                mhd.codeVersion       = codeVersion;
                                mhd.InUse             = false;
                                mhd.hostPortIPAddress = hostPortIPAddress;

                                if (targetIP != null)
                                {
                                    if (mhd.IPAddress.CompareTo(targetIP.ToString()) == 0)
                                    {
                                        have_Metis = true;
                                        mhdList.Add(mhd);
                                        return(true);
                                    }
                                }
                                else
                                {
                                    have_Metis = true;
                                    mhdList.Add(mhd);
                                }
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("No data  from Port = ");
                        if ((++time_out) > 5)
                        {
                            Console.WriteLine("Time out!");
                            return(false);
                        }
                    }
                } while (data_available);
            }

            return(have_Metis);
        }