// The main USB dump routine static void usb_dump (int num_packets) { // Packets will be saved during the collapse process PacketQueue pkt_q; // Points to the current packet PacketInfo * cur_pkt; // Collapsing counts and time collapsing started CollapseInfo collapse_info; // Collapsing of packets is handled through a state machine. // Sometimes the machine will need to be re-run to properly // handle the sequence of packets. enum CollapseStates { IDLE = 0, IN, PING, SPLIT, SPLIT_IN, SPLIT_OUT, SPLIT_SETUP } state = IDLE; u08 re_run = FALSE; u08 pid = 0; int signal_errors = 0; int packetnum = 0; // Initialize structures memset(&pkt_q, 0, sizeof(PacketQueue)); memset(&collapse_info, 0, sizeof(CollapseInfo)); samplerate_khz = bg_samplerate(beagle, 0); // Configure Beagle 480 for realtime capture bg_usb480_capture_configure(beagle, BG_USB480_CAPTURE_REALTIME, BG_USB2_AUTO_SPEED_DETECT); // Filter packets intended for the Beagle analyzer. This is only // relevant when one host controller is being used. bg_usb480_hw_filter_config(beagle, BG_USB2_HW_FILTER_SELF); if (bg_enable(beagle, BG_PROTOCOL_USB) != BG_OK) { printf("error: could not enable USB capture; exiting...\n"); exit(1); } // Output the header... printf("index,time(ns),USB,status,pid,data0 ... dataN(*)\n"); fflush(stdout); // ...then start decoding packets while (packetnum < num_packets || !num_packets) { cur_pkt = &pkt_q.pkt[pkt_q.tail]; cur_pkt->length = bg_usb480_read(beagle, &cur_pkt->status, &cur_pkt->events, &cur_pkt->time_sop, &cur_pkt->time_duration, &cur_pkt->time_dataoffset, 1024, cur_pkt->data); cur_pkt->time_sop_ns = TIMESTAMP_TO_NS(cur_pkt->time_sop, samplerate_khz); // Exit if observed end of capture if (cur_pkt->status & BG_READ_USB_END_OF_CAPTURE) { usb_print_summary_packet(&packetnum, &collapse_info, &signal_errors); break; } // Check for invalid packet or Beagle error if (cur_pkt->length < 0) { char error_status[32]; sprintf(error_status, "error=%d", cur_pkt->length); usb_print_packet(packetnum, cur_pkt, error_status); break; } // Check for USB error if (cur_pkt->status == BG_READ_USB_ERR_BAD_SIGNALS) ++signal_errors; // Set the PID for collapsing state machine below. Treat // KEEP_ALIVEs as packets. if (cur_pkt->length > 0) pid = cur_pkt->data[0]; else if ((cur_pkt->events & BG_EVENT_USB_KEEP_ALIVE) && !(cur_pkt->status & BG_READ_USB_ERR_BAD_PID)) { pid = 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 ((int)(cur_pkt->time_sop - collapse_info.time_sop) >= IDLE_SAMPLES) usb_print_summary_packet(&packetnum, &collapse_info, &signal_errors); while(1) { re_run = 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 IDLE: switch (pid) { case KEEP_ALIVE: COLLAPSE(KEEP_ALIVE); break; case BG_USB_PID_SOF: COLLAPSE(SOF); break; case BG_USB_PID_IN: SAVE_PACKET(); state = IN; break; case BG_USB_PID_PING: SAVE_PACKET(); state = PING; break; case BG_USB_PID_SPLIT: SAVE_PACKET(); state = SPLIT; break; default: usb_print_summary_packet(&packetnum, &collapse_info, &signal_errors); if (cur_pkt->length > 0 || cur_pkt->events || (cur_pkt->status != 0 && cur_pkt->status != BG_READ_TIMEOUT)) { usb_print_packet(packetnum, cur_pkt, 0); packetnum++; } } break; // Collapsing IN+ACK or IN+NAK. Otherwise, output any // saved packets and rerun the collapsing state machine // on the current packet. case IN: state = IDLE; switch (pid) { case BG_USB_PID_ACK: COLLAPSE(IN_ACK); break; case BG_USB_PID_NAK: COLLAPSE(IN_NAK); break; default: re_run = TRUE; } break; // Collapsing PING+NAK case PING: state = IDLE; switch (pid) { case BG_USB_PID_NAK: COLLAPSE(PING_NAK); break; default: re_run = TRUE; } break; // Expecting an IN, OUT, or SETUP case SPLIT: switch (pid) { case BG_USB_PID_IN: SAVE_PACKET(); state = SPLIT_IN; break; case BG_USB_PID_OUT: SAVE_PACKET(); state = SPLIT_OUT; break; case BG_USB_PID_SETUP: SAVE_PACKET(); state = SPLIT_SETUP; break; default: state = IDLE; re_run = TRUE; } break; // Collapsing SPLIT+IN+NYET, SPLIT+IN+NAK, SPLIT+IN+ACK case SPLIT_IN: state = IDLE; switch (pid) { case BG_USB_PID_NYET: COLLAPSE(SPLIT_IN_NYET); break; case BG_USB_PID_NAK: COLLAPSE(SPLIT_IN_NAK); break; case BG_USB_PID_ACK: COLLAPSE(SPLIT_IN_ACK); break; default: re_run = TRUE; } break; // Collapsing SPLIT+OUT+NYET case SPLIT_OUT: state = IDLE; switch (pid) { case BG_USB_PID_NYET: COLLAPSE(SPLIT_OUT_NYET); break; default: re_run = TRUE; } break; // Collapsing SPLIT+SETUP+NYET case SPLIT_SETUP: state = IDLE; switch (pid) { case BG_USB_PID_NYET: COLLAPSE(SPLIT_SETUP_NYET); break; default: re_run = TRUE; } break; } if (re_run == 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. OUTPUT_SAVED(); } } // Stop the capture bg_disable(beagle); }
void collapseDuplexGroup(string sorted_duplex_group_file, string collapsed_dg_file, string logFile, string errorFile, int maxGap, int maxTotal) { ofstream LOG(logFile, ios_base::app); ofstream ERR(errorFile, ios_base::app); LOG << "Start to collapseDuplexGroup " << sorted_duplex_group_file << " ===> " << collapsed_dg_file << endl; int merged_dgCount = 0; int firstPossible=0; PointerArray<DuplexGroup *> dgArray; long long fileLines = countFileLines(sorted_duplex_group_file); ProcessAlert alert(fileLines, 100000, 10); ifstream DUPLEXGROUP(sorted_duplex_group_file); char strand1, strand2; string chr1, chr2, supportReads; int start1, end1, start2, end2, support; while(DUPLEXGROUP>>chr1>>start1>>end1>>strand1>>chr2>>start2>>end2>>strand2>>supportReads>>support) { char buffer[200]; sprintf(buffer, "firstPossible: %d, merged_dgCount: %d", firstPossible, merged_dgCount); LOG << alert.alert(string(buffer)); DuplexGroup *dg = new DuplexGroup(chr1, start1, end1, strand1, chr2, start2,end2, strand2, support, supportReads); //dgArray.append(dg); //if(supportReads == "23198;10015265;10015267;10015268") // cout << dgArray[dgArray.arrayLen()-1]->supportRead << endl; int lastDGovarlapped = 0; bool merged = false; for(int idx=firstPossible; idx<dgArray.arrayLen();idx++) { int overlapped = dgArray[idx]->overlapDG(dg, maxGap, maxTotal); /* if(supportReads == "23198;10015265;10015267;10015268" and idx==dgArray.arrayLen()-1) { cout << dgArray[dgArray.arrayLen()-1]->supportRead << endl; cout <<overlapped << endl; } */ if (overlapped == -1){ if(not lastDGovarlapped) firstPossible = idx + 1; } else if(overlapped > 0){ lastDGovarlapped = 1; dgArray[idx]->mergeDuplexGroup(dg); //dgArray.del(dgArray.arrayLen()-1); merged = true; delete dg; merged_dgCount++; break; } else{ lastDGovarlapped = 1; } } if(not merged) dgArray.append(dg); //cout << merged_dgCount << endl; } LOG << alert.finish(); DUPLEXGROUP.close(); ofstream COLLAPSE(collapsed_dg_file); for(int i=0; i<dgArray.arrayLen(); i++) COLLAPSE << dgArray[i]->chr1 << "\t" << dgArray[i]->start1 << "\t" << dgArray[i]->end1 << "\t" << dgArray[i]->strand1 << "\t" << dgArray[i]->chr2 << "\t" << dgArray[i]->start2 << "\t" << dgArray[i]->end2 << "\t" << dgArray[i]->strand2 << "\t" << dgArray[i]->supportRead << "\t" << dgArray[i]->support << "\n"; COLLAPSE.close(); LOG.close(); ERR.close(); }