// Check the given UsbStream for a valid WireProtocol packet (header). Returns true // along with the WP_Packet (header) if available. Returns false if nothing valid received as yet. public static bool ReadPacket(UsbStream stream, out WP_Packet packet) { packet = new WP_Packet(); byte[] buffer = new byte[WP_Packet.packetSize]; // Size of marshalled WP_Packet int nRead; // Read in enough data for a complete WP_Packet (header) nRead = stream.Read(buffer, 0, WP_Packet.packetSize); // If there were not enough bytes to fill the complete WP_Packet, it's no good if (nRead != WP_Packet.packetSize) { return false; } // Unmarshal the signature string from the buffer to the WP_Packet packet.m_signature = ""; for (int i = 0; (i < WP_Packet.m_crcHeader_offset) && (buffer[i] != 0); i++) { packet.m_signature += (char)buffer[i]; } // Unmarshal the rest of the buffer into the WP_Packet structure. packet.m_crcHeader = ReadUINT32(buffer, WP_Packet.m_crcHeader_offset); packet.m_crcData = ReadUINT32(buffer, WP_Packet.m_crcData_offset); packet.m_seq = ReadUINT16(buffer, WP_Packet.m_seq_offset); packet.m_seqReply = ReadUINT16(buffer, WP_Packet.m_seqReply_offset); packet.m_flags = ReadUINT32(buffer, WP_Packet.m_flags_offset); packet.m_size = ReadUINT32(buffer, WP_Packet.m_size_offset); packet.m_cmd = (Commands)ReadUINT32(buffer, WP_Packet.m_cmd_offset); // The header CRC must first be zeroed to calculate the correct header CRC WriteUINT32(buffer, WP_Packet.m_crcHeader_offset, 0); // If the calculated CRC does not match that of the packet, it is no good if (packet.m_crcHeader != SUPPORT_ComputeCRC(buffer, 0, WP_Packet.packetSize, 0)) { return false; } return true; }
// Accepts only a good packet. If the packet is a Ping, the Ping response (ACK) is sent. // Otherwise, the command is NAK'ed. static bool RespondToPacket(UsbStream pinger, WireProtocol.WP_Packet inPacket, UInt16 seq) { WireProtocol.WP_Packet outPacket = new WireProtocol.WP_Packet(); // Allocate space for any data following the packet int size = (int)(inPacket.m_size & 0xFFFF); byte[] buffer = new byte[size]; // Read in the data that came with the packet if (inPacket.m_size != 0) pinger.Read(buffer, 0, size); // Fill in the blanks of the response packet outPacket.m_signature = "MSdbgV1"; // Standard target signature outPacket.m_cmd = inPacket.m_cmd; // Show which command this is a response to outPacket.m_seq = seq++; // Keep track of the target message sequence number outPacket.m_seqReply = inPacket.m_seq; // Show which host packet sequence number this is a response to // If the host packet was a Ping if (inPacket.m_cmd == WireProtocol.Commands.Ping) { byte[] data = new byte[8]; // The Ping has an 8 byte data response outPacket.m_flags = 0x8003; // Return a low-priority ACK for (int i = 0; i < 8; i++) data[i] = 0; // Initialize all bytes of the data response to zero data[0] = 1; // This tells the host that we are TinyBooter data[4] = 2; // This is an innoccuous flag value WireProtocol.SendPacket(pinger, outPacket, data); // Send response to the Ping } else { outPacket.m_flags = 0x4003; // Return a low-priority NACK WireProtocol.SendPacket(pinger, outPacket, new byte[0]); // Signal to the host that we don't know what to do with the command } return true; }