Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 1 | #include "frc971/can_logger/can_logger.h" |
| 2 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame^] | 3 | namespace frc971::can_logger { |
Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 4 | |
Maxwell Henderson | 0604e6f | 2024-01-15 15:24:44 -0800 | [diff] [blame] | 5 | CanLogger::CanLogger(aos::ShmEventLoop *event_loop, |
| 6 | std::string_view channel_name, |
Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 7 | std::string_view interface_name) |
| 8 | : fd_(socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)), |
Maxwell Henderson | 0604e6f | 2024-01-15 15:24:44 -0800 | [diff] [blame] | 9 | frames_sender_(event_loop->MakeSender<CanFrame>(channel_name)) { |
Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 10 | struct ifreq ifr; |
| 11 | strcpy(ifr.ifr_name, interface_name.data()); |
| 12 | PCHECK(ioctl(fd_.get(), SIOCGIFINDEX, &ifr) == 0) |
| 13 | << "Failed to get index for interface " << interface_name; |
| 14 | |
| 15 | int enable_canfd = true; |
| 16 | PCHECK(setsockopt(fd_.get(), SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, |
| 17 | sizeof(enable_canfd)) == 0) |
| 18 | << "Failed to enable CAN FD"; |
| 19 | |
| 20 | struct sockaddr_can addr; |
| 21 | addr.can_family = AF_CAN; |
| 22 | addr.can_ifindex = ifr.ifr_ifindex; |
| 23 | |
| 24 | PCHECK(bind(fd_.get(), reinterpret_cast<struct sockaddr *>(&addr), |
| 25 | sizeof(addr)) == 0) |
| 26 | << "Failed to bind socket to interface " << interface_name; |
| 27 | |
| 28 | int recieve_buffer_size; |
| 29 | socklen_t opt_size = sizeof(recieve_buffer_size); |
| 30 | PCHECK(getsockopt(fd_.get(), SOL_SOCKET, SO_RCVBUF, &recieve_buffer_size, |
| 31 | &opt_size) == 0); |
| 32 | CHECK_EQ(opt_size, sizeof(recieve_buffer_size)); |
| 33 | VLOG(0) << "CAN recieve bufffer is " << recieve_buffer_size << " bytes large"; |
| 34 | |
Maxwell Henderson | 0604e6f | 2024-01-15 15:24:44 -0800 | [diff] [blame] | 35 | event_loop->epoll()->OnReadable(fd_, [this]() { Poll(); }); |
Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | void CanLogger::Poll() { |
| 39 | VLOG(2) << "Polling"; |
| 40 | int frames_read = 0; |
| 41 | while (ReadFrame()) { |
| 42 | frames_read++; |
| 43 | } |
| 44 | VLOG(1) << "Read " << frames_read << " frames to end of buffer"; |
| 45 | } |
| 46 | |
| 47 | bool CanLogger::ReadFrame() { |
| 48 | errno = 0; |
| 49 | struct canfd_frame frame; |
| 50 | ssize_t bytes_read = read(fd_.get(), &frame, sizeof(struct canfd_frame)); |
| 51 | |
| 52 | if (bytes_read < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { |
| 53 | // There are no more frames sitting in the recieve buffer. |
| 54 | return false; |
| 55 | } |
| 56 | |
| 57 | VLOG(2) << "Read " << bytes_read << " bytes"; |
| 58 | PCHECK(bytes_read > 0); |
| 59 | PCHECK(bytes_read == static_cast<ssize_t>(CAN_MTU) || |
| 60 | bytes_read == static_cast<ssize_t>(CANFD_MTU)) |
| 61 | << "Incomplete can frame"; |
| 62 | |
| 63 | struct timeval tv; |
| 64 | PCHECK(ioctl(fd_.get(), SIOCGSTAMP, &tv) == 0) |
| 65 | << "Failed to get timestamp of CAN frame"; |
| 66 | |
| 67 | aos::Sender<CanFrame>::Builder builder = frames_sender_.MakeBuilder(); |
| 68 | |
| 69 | auto frame_data = builder.fbb()->CreateVector<uint8_t>(frame.data, frame.len); |
| 70 | |
| 71 | CanFrame::Builder can_frame_builder = builder.MakeBuilder<CanFrame>(); |
| 72 | can_frame_builder.add_can_id(frame.can_id); |
Ravago Jones | 6f64176 | 2023-03-29 19:58:32 -0700 | [diff] [blame] | 73 | can_frame_builder.add_flags(frame.flags); |
Ravago Jones | 1147237 | 2023-03-04 15:57:56 -0800 | [diff] [blame] | 74 | can_frame_builder.add_data(frame_data); |
| 75 | can_frame_builder.add_monotonic_timestamp_ns( |
| 76 | static_cast<std::chrono::nanoseconds>( |
| 77 | std::chrono::seconds(tv.tv_sec) + |
| 78 | std::chrono::microseconds(tv.tv_usec)) |
| 79 | .count()); |
| 80 | |
| 81 | builder.CheckOk(builder.Send(can_frame_builder.Finish())); |
| 82 | |
| 83 | return true; |
| 84 | } |
| 85 | |
Stephan Pleines | f63bde8 | 2024-01-13 15:59:33 -0800 | [diff] [blame^] | 86 | } // namespace frc971::can_logger |