예제 #1
0
// Outputs any packets saved during the collapsing process
static void output_saved (int          * packetnum,
                          int          * signal_errors,
                          CollapseInfo * collapse_info,
                          PacketQueue  * pkt_q)
{
    usb_print_summary_packet(packetnum, collapse_info, signal_errors);

    while (pkt_q->head != pkt_q->tail) {
        usb_print_packet(*packetnum, &pkt_q->pkt[pkt_q->head], 0);
        *packetnum += 1;
        pkt_q->head = (pkt_q->head + 1) % QUEUE_SIZE;
    }
}
예제 #2
0
파일: cli.c 프로젝트: MarcoPolo/vfs301
int usb_recv(vfs_dev_t *dev, unsigned char endpoint, int max_bytes)
{
	int transferred = 0;
	
	assert(max_bytes <= sizeof(dev->recv_buf));
	
	int r = libusb_bulk_transfer(
		dev->devh, endpoint, 
		dev->recv_buf, max_bytes,
		&dev->recv_len, VALIDITY_DEFAULT_WAIT_TIMEOUT
	);
	
#ifdef DEBUG
	usb_print_packet(0, r, dev->recv_buf, dev->recv_len);
#endif
	
	if (r < 0)
		return r;
	return 0;
}
예제 #3
0
파일: cli.c 프로젝트: MarcoPolo/vfs301
int usb_send(vfs_dev_t *dev, const unsigned char *data, int length)
{
	int transferred = 0;
	
	int r = libusb_bulk_transfer(
		dev->devh, VALIDITY_SEND_ENDPOINT, 
		(unsigned char *)data, length, &transferred, VALIDITY_DEFAULT_WAIT_TIMEOUT
	);

#ifdef DEBUG
	usb_print_packet(1, r, data, length);
#endif
	
	assert(r == 0);
	
	if (r < 0)
		return r;
	if (transferred < length)
		return r;
	
	return 0;
}
예제 #4
0
// 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);
}