diff --git a/selfdrive/boardd/panda.cc b/selfdrive/boardd/panda.cc index 75458974fc..751f735ca5 100644 --- a/selfdrive/boardd/panda.cc +++ b/selfdrive/boardd/panda.cc @@ -363,57 +363,49 @@ static uint8_t len_to_dlc(uint8_t len) { } } -void Panda::pack_can_buffer(const capnp::List::Reader &can_data_list, - std::function write_func) { - if (send.size() < (can_data_list.size() * CANPACKET_MAX_SIZE)) { - send.resize(can_data_list.size() * CANPACKET_MAX_SIZE); +static void write_packet(uint8_t *dest, int *write_pos, const uint8_t *src, size_t size) { + for (int i = 0, &pos = *write_pos; i < size; ++i, ++pos) { + // Insert counter every 64 bytes (first byte of 64 bytes USB packet) + if (pos % USBPACKET_MAX_SIZE == 0) { + dest[pos] = pos / USBPACKET_MAX_SIZE; + pos++; + } + dest[pos] = src[i]; } +} - int msg_count = 0; - while (msg_count < can_data_list.size()) { - uint32_t pos = 0; - while (pos < USB_TX_SOFT_LIMIT) { - if (msg_count == can_data_list.size()) { break; } - auto cmsg = can_data_list[msg_count]; - - // check if the message is intended for this panda - uint8_t bus = cmsg.getSrc(); - if (bus < bus_offset || bus >= (bus_offset + PANDA_BUS_CNT)) { - msg_count++; - continue; - } - auto can_data = cmsg.getDat(); - uint8_t data_len_code = len_to_dlc(can_data.size()); - assert(can_data.size() <= ((hw_type == cereal::PandaState::PandaType::RED_PANDA) ? 64 : 8)); - assert(can_data.size() == dlc_to_len[data_len_code]); - - can_header header; - header.addr = cmsg.getAddress(); - header.extended = (cmsg.getAddress() >= 0x800) ? 1 : 0; - header.data_len_code = data_len_code; - header.bus = bus - bus_offset; - memcpy(&send[pos], &header, CANPACKET_HEAD_SIZE); - memcpy(&send[pos+CANPACKET_HEAD_SIZE], can_data.begin(), can_data.size()); - - pos += CANPACKET_HEAD_SIZE + dlc_to_len[data_len_code]; - msg_count++; +void Panda::pack_can_buffer(const capnp::List::Reader &can_data_list, + std::function write_func) { + int32_t pos = 0; + uint8_t send_buf[2 * USB_TX_SOFT_LIMIT]; + + for (auto cmsg : can_data_list) { + // check if the message is intended for this panda + uint8_t bus = cmsg.getSrc(); + if (bus < bus_offset || bus >= (bus_offset + PANDA_BUS_CNT)) { + continue; } + auto can_data = cmsg.getDat(); + uint8_t data_len_code = len_to_dlc(can_data.size()); + assert(can_data.size() <= ((hw_type == cereal::PandaState::PandaType::RED_PANDA) ? 64 : 8)); + assert(can_data.size() == dlc_to_len[data_len_code]); - if (pos > 0) { // Helps not to spam with ZLP - // Counter needs to be inserted every 64 bytes (first byte of 64 bytes USB packet) - uint8_t counter = 0; - uint8_t to_write[USB_TX_SOFT_LIMIT+128]; - int ptr = 0; - for (int i = 0; i < pos; i += 63) { - to_write[ptr] = counter; - int copy_size = ((pos - i) < 63) ? (pos - i) : 63; - memcpy(&to_write[ptr+1], &(send.data()[i]) , copy_size); - ptr += copy_size + 1; - counter++; - } - write_func(to_write, ptr); + can_header header; + header.addr = cmsg.getAddress(); + header.extended = (cmsg.getAddress() >= 0x800) ? 1 : 0; + header.data_len_code = data_len_code; + header.bus = bus - bus_offset; + + write_packet(send_buf, &pos, (uint8_t *)&header, sizeof(can_header)); + write_packet(send_buf, &pos, (uint8_t *)can_data.begin(), can_data.size()); + if (pos >= USB_TX_SOFT_LIMIT) { + write_func(send_buf, pos); + pos = 0; } } + + // send remaining packets + if (pos > 0) write_func(send_buf, pos); } void Panda::can_send(capnp::List::Reader can_data_list) { diff --git a/selfdrive/boardd/panda.h b/selfdrive/boardd/panda.h index 79124a59b1..fe69189489 100644 --- a/selfdrive/boardd/panda.h +++ b/selfdrive/boardd/panda.h @@ -69,7 +69,6 @@ class Panda { libusb_context *ctx = NULL; libusb_device_handle *dev_handle = NULL; std::mutex usb_lock; - std::vector send; std::vector recv_buf; void handle_usb_issue(int err, const char func[]); void cleanup();