static void usbDump(int numPackets) { // Packets are saved during the collapsing process PacketQueue pktQ = new PacketQueue(); // Info for the packet that was just read PacketInfo curPacket; // Collapsing counts and time collapsing started CollapseInfo collapseInfo = new CollapseInfo(); CollapseState state = CollapseState.IDLE; bool reRun = false; byte pid = 0; int signalErrors = 0; int packetnum = 0; samplerateKHz = BeagleApi.bg_samplerate(beagle, 0); int idle_samples = IDLE_THRESHOLD * samplerateKHz; // Configure Beagle 480 for realtime capture BeagleApi.bg_usb480_capture_configure(beagle, BeagleUsb480CaptureMode.BG_USB480_CAPTURE_REALTIME, BeagleUsb2TargetSpeed.BG_USB2_AUTO_SPEED_DETECT); // Filter packets intended for the Beagle analyzer. This is only // relevant when one host controller is being used. BeagleApi.bg_usb480_hw_filter_config(beagle, BeagleApi.BG_USB2_HW_FILTER_SELF); // Start the capture if (BeagleApi.bg_enable(beagle, BeagleProtocol.BG_PROTOCOL_USB) != (int)BeagleStatus.BG_OK) { Console.Write("error: could not enable USB capture; exiting...\n"); Environment.Exit(1); } // Output the header... Console.Write("index,time(ns),USB,status,pid,data0 ... dataN(*)\n"); Console.Out.Flush(); // ...then start decoding packets while (packetnum < numPackets || (numPackets == 0)) { curPacket = pktQ.getTail(); curPacket.length = BeagleApi.bg_usb480_read( beagle, ref curPacket.status, ref curPacket.events, ref curPacket.timeSop, ref curPacket.timeDuration, ref curPacket.timeDataOffset, 1024, curPacket.data); curPacket.timeSopNS = timestampToNS(curPacket.timeSop, samplerateKHz); // Exit if observed end of capture if ((curPacket.status & BeagleApi.BG_READ_USB_END_OF_CAPTURE) != 0) { usbPrintSummaryPacket(ref packetnum, collapseInfo, ref signalErrors); break; } // Check for invalid packet or Beagle error if (curPacket.length < 0) { String errorStatus = ""; errorStatus += String.Format("error={0:d}", curPacket.length); usbPrintPacket(packetnum, curPacket, errorStatus); break; } // Check for USB error if (curPacket.status == BeagleApi.BG_READ_USB_ERR_BAD_SIGNALS) { ++signalErrors; } // Set the PID for collapsing state machine below. Treat // KEEP_ALIVEs as packets. if (curPacket.length > 0) { pid = curPacket.data[0]; } else if ((curPacket.events & BeagleApi.BG_EVENT_USB_KEEP_ALIVE) != 0 && (curPacket.status & BeagleApi.BG_READ_USB_ERR_BAD_PID) == 0) { pid = (byte)PacketGroup.KEEP_ALIVE; } else { pid = 0; } // Collapse these packets approprietly: // KEEP_ALIVE* SOF* (IN (ACK|NAK))* (PING NAK)* // (SPLIT (OUT|SETUP) NYET)* (SPLIT IN (ACK|NYET|NACK))* // If the time elapsed since collapsing began is greater than // the threshold, output the counts and zero out the counters. if (curPacket.timeSop - collapseInfo.timeSop >= (ulong)idle_samples) { usbPrintSummaryPacket(ref packetnum, collapseInfo, ref signalErrors); } while (true) { reRun = false; switch (state) { // The initial state of the state machine. Collapse SOFs // and KEEP_ALIVEs. Save IN, PING, or SPLIT packets and // move to the next state for the next packet. Otherwise, // print the collapsed packet counts and the current // packet. case CollapseState.IDLE: switch (pid) { case (byte)PacketGroup.KEEP_ALIVE: collapse(PacketGroup.KEEP_ALIVE, collapseInfo, pktQ); break; case BeagleApi.BG_USB_PID_SOF: collapse(PacketGroup.SOF, collapseInfo, pktQ); break; case BeagleApi.BG_USB_PID_IN: pktQ.savePacket(); state = CollapseState.IN; break; case BeagleApi.BG_USB_PID_PING: pktQ.savePacket(); state = CollapseState.PING; break; case BeagleApi.BG_USB_PID_SPLIT: pktQ.savePacket(); state = CollapseState.SPLIT; break; default: usbPrintSummaryPacket(ref packetnum, collapseInfo, ref signalErrors); if (curPacket.length > 0 || curPacket.events != 0 || (curPacket.status != 0 && curPacket.status != BeagleApi.BG_READ_TIMEOUT)) { usbPrintPacket(packetnum, curPacket, null); packetnum++; } break; } break; // Collapsing IN+ACK or IN+NAK. Otherwise, output any // saved packets and rerun the collapsing state machine // on the current packet. case CollapseState.IN: state = CollapseState.IDLE; switch (pid) { case BeagleApi.BG_USB_PID_ACK: collapse(PacketGroup.IN_ACK, collapseInfo, pktQ); break; case BeagleApi.BG_USB_PID_NAK: collapse(PacketGroup.IN_NAK, collapseInfo, pktQ); break; default: reRun = true; break; } break; // Collapsing PING+NAK case CollapseState.PING: state = CollapseState.IDLE; switch (pid) { case BeagleApi.BG_USB_PID_NAK: collapse(PacketGroup.PING_NAK, collapseInfo, pktQ); break; default: reRun = true; break; } break; // Expecting an IN, OUT, or SETUP case CollapseState.SPLIT: switch (pid) { case BeagleApi.BG_USB_PID_IN: pktQ.savePacket(); state = CollapseState.SPLIT_IN; break; case BeagleApi.BG_USB_PID_OUT: pktQ.savePacket(); state = CollapseState.SPLIT_OUT; break; case BeagleApi.BG_USB_PID_SETUP: pktQ.savePacket(); state = CollapseState.SPLIT_SETUP; break; default: state = CollapseState.IDLE; reRun = true; break; } break; // Collapsing SPLIT+IN+NYET, SPLIT+IN+NAK, SPLIT+IN+ACK case CollapseState.SPLIT_IN: state = CollapseState.IDLE; switch (pid) { case BeagleApi.BG_USB_PID_NYET: collapse(PacketGroup.SPLIT_IN_NYET, collapseInfo, pktQ); break; case BeagleApi.BG_USB_PID_NAK: collapse(PacketGroup.SPLIT_IN_NAK, collapseInfo, pktQ); break; case BeagleApi.BG_USB_PID_ACK: collapse(PacketGroup.SPLIT_IN_ACK, collapseInfo, pktQ); break; default: reRun = true; break; } break; // Collapsing SPLIT+OUT+NYET case CollapseState.SPLIT_OUT: state = CollapseState.IDLE; switch (pid) { case BeagleApi.BG_USB_PID_NYET: collapse(PacketGroup.SPLIT_OUT_NYET, collapseInfo, pktQ); break; default: reRun = true; break; } break; // Collapsing SPLIT+SETUP+NYET case CollapseState.SPLIT_SETUP: state = CollapseState.IDLE; switch (pid) { case BeagleApi.BG_USB_PID_NYET: collapse(PacketGroup.SPLIT_SETUP_NYET, collapseInfo, pktQ); break; default: reRun = true; break; } break; } if (reRun == false) { break; } // The state machine is about to be re-run. This // means that a complete packet sequence wasn't collapsed // and there are packets in the queue that need to be // output before we can process the current packet. outputSaved(ref packetnum, ref signalErrors, collapseInfo, pktQ); } } // Stop the capture BeagleApi.bg_disable(beagle); }
static void usbDump(int numPackets, int timeoutMS) { long start, elapsedTime; // Set up variables byte[] packet = new byte[1024]; int packetnum = 0; samplerateKhz = BeagleApi.bg_samplerate(beagle, 0); // Configure Beagle 480 for delayed-download capture BeagleApi.bg_usb480_capture_configure(beagle, BeagleUsb480CaptureMode.BG_USB480_CAPTURE_DELAYED_DOWNLOAD, BeagleUsb2TargetSpeed.BG_USB2_AUTO_SPEED_DETECT); // Enable the hardware filtering. This will filter out packets with // the same device address as the Beagle analyzer and also filter // the PID packet groups listed below. BeagleApi.bg_usb480_hw_filter_config(beagle, BeagleApi.BG_USB2_HW_FILTER_SELF | BeagleApi.BG_USB2_HW_FILTER_PID_SOF | BeagleApi.BG_USB2_HW_FILTER_PID_IN | BeagleApi.BG_USB2_HW_FILTER_PID_PING | BeagleApi.BG_USB2_HW_FILTER_PID_PRE | BeagleApi.BG_USB2_HW_FILTER_PID_SPLIT); // Start the capture portion of the delayed-download capture if (BeagleApi.bg_enable(beagle, BeagleProtocol.BG_PROTOCOL_USB) != (int)BeagleStatus.BG_OK) { Console.Write("error: could not enable USB capture; exiting...\n"); Environment.Exit(1); } // Wait until timeout period elapses or the hardware buffer on // the Beagle USB 480 fills Console.Write("Hardware buffer usage:\n"); start = timeMicroseconds(); while (true) { uint bufferSize = 0; uint bufferUsage = 0; byte bufferFull = 0; // Poll the hardware buffer status BeagleApi.bg_usb480_hw_buffer_stats(beagle, ref bufferSize, ref bufferUsage, ref bufferFull); // Print out the progress elapsedTime = (timeMicroseconds() - start) / 1000; printProgress(bufferUsage / (bufferSize / 100), ((double)elapsedTime) / 1000, bufferUsage, bufferSize); // If timed out or buffer is full, exit loop if (bufferFull != 0 || (timeoutMS != 0 && elapsedTime > timeoutMS)) { break; } // Sleep for 150 milliseconds BeagleApi.bg_sleep_ms(150); } // Start the download portion of the delayed-download capture // // Output the header... Console.Write("\nindex,time(ns),USB,status,pid,data0 ... dataN(*)\n"); Console.Out.Flush(); // ...then start decoding packets while (packetnum < numPackets || (numPackets == 0)) { uint status = 0; uint events = 0; ulong timeSop = 0; ulong timeSopNS = 0; ulong timeDuration = 0; uint timeDataOffset = 0; // Calling bg_usb480_read will automatically stop the // capture portion of the delayed-download capture and // will begin downloading the capture results. int length = BeagleApi.bg_usb480_read( beagle, ref status, ref events, ref timeSop, ref timeDuration, ref timeDataOffset, 1024, packet); timeSopNS = TIMESTAMP_TO_NS(timeSop, samplerateKhz); // Check for invalid packet or Beagle error if (length < 0) { String errorStatus = ""; errorStatus += String.Format("error={0:d}", length); usbPrintPacket(packetnum, timeSopNS, status, events, errorStatus, null); break; } // Output the current transaction if (length > 0 || events != 0 || (status != 0 && status != BeagleApi.BG_READ_TIMEOUT)) { String packetData = usbPrintDataPacket(ref packet, length); usbPrintPacket(packetnum, timeSopNS, status, events, null, packetData); ++packetnum; } // Exit if observe end of capture if ((status & BeagleApi.BG_READ_USB_END_OF_CAPTURE) != 0) { break; } } // Stop the capture BeagleApi.bg_disable(beagle); }