 Thanks for coming out. My name is Eric Evingczyk. I work for a company called the Tredis. We do embedded in mobile and all sorts of assessments of things. And I also play with cars a bunch and can bus a bunch and that's kind of my deal. So recently I was playing around with some tools and I was like, hey, go-lang is kind of nifty. I want to play around with cars and go-lang at the same time. So we have the little go-go for it and we have your quintessential car hacker because that's how you hack a car. You take a Mac book, worry about the clava, you're good to go. So has anyone here written some can bus tools, maybe played around with like socket can, written some stuff, maybe some folks in the audience? I don't know. But if you want to write a tool, you need some things. And the first thing is because cars mostly talk can nowadays, you need to be able to talk can. That's like a first pass thing. Concurrency is super useful. And the reason for this is whenever you're dealing with a can bus, there's a lot of times that you're sitting there and you're waiting for a frame to come in and you're waiting. You want to do other things. You want to be able to time out. You want to fail nicely. You want to be able to do that sort of thing. If you don't have concurrency, then you'd deadlock, things like that. So having access to nice concurrency features is a really, really good thing when you're writing these types of tools. So we're going to pick a language that we're going to write our tool in and traditionally a lot of these have been C and C++ and Python. I've written a lot of stuff in Python, but I'm not smart enough to understand Python's new async.io because it's crazy. And P threads are a bit of a pain. So that's why we might want to go. There's a few reasons. What's in concurrency? So anyone in the audience written a line of go-lang in their life, maybe? A couple of people. Cool. If you haven't, I recommend it. The tutorial on the go-lang website, it like runs in your browser and you can step through it. It's got lots of great examples. It's lovely. But one really nifty thing about go is it's got these things that it calls go-routines, which is a pun, which is one reason I love the language. It's got puns. And that is actually a co-routine. So it will allow you to run a separate, you know, not thread, it's a co-routine, but it's run over here at the same time. And it also has channels, which allow you to do synchronized communication back and forth between these different routines that are running. And all of this is implemented in the go-run time, not at the OS level. So if you run on Windows, Linux, OSX, whatever, you get the same sort of thing happening. You're not relying on some OS API. So the concurrency is built in is really nice. It was thought of originally, because Google wrote this language in order to actually like write web servers where concurrency kind of important. It's typed, which if you've ever like started writing a project in Python and it got to a certain size, you probably went, I regret choosing Python now. Typing is really nice whenever you are passing things around with different modules and things like that, and you want the data to not go to space. So I like typed languages. And yeah, it's a compiled language. And this is great because often when you're using scripting languages, you write, you know, a tool in Python, whatever it is. And then you have all these dependencies you got to pull down. And if they have the wrong version, it's not going to work. And they're not in line. They can't pull it down from PIP and all that sort of stuff. You build a go binary. You can build a like statically linked binary. That's a single binary. You run it and it works. And as of the whole purpose of this talk is, as of right now, it supports socket can, which means that we can do can bus for it. So socket can, what is this? I think there's talks on socket can here. I'm going to be kind of brief. But socket can is can over standard Unix socket. So Unix sockets have you ever written any code on Unix or any Unix system, some web server, something like that. You know, you have these socket as file descriptor, you set the thing up, you bind to it, and then you can read and write to it. You can also do a lot of other things, but that's the basic functionality. And that's usually used for network stuff, TCP, IP, you know, that's how it's been used traditionally. But we can also do can from it. Any question here? Slides? I will make them available. I will toss them in with the repo for this. So whether this works for you in when you're doing can, you have an application and I stuck the little gopher in a plane, because that's going to be written in go. And then that's going to talk to the socket layer of your OS, which is in the kernel. And where socket can jumps in here, you know, most the time you'd have a protocol family, which is your standard ethernet, internet protocols, UDP, TCP, but we can have a can protocol family, and we can talk to it that way. And then that will talk to the device drivers and eventually the actual hardware. And this is super nice because it means it's hardware agnostic. If your hardware device supports socket can, you don't care what device it is, you just send frames and it works. So for when it doesn't, but usually if they've implemented a write, it would work. And so it's hard to agnostic, we don't care as long as the thing is going to create a socket we can make go. So how do we do this and go? Well, we can do this like any other socket we do, you know, file descriptor and error is equal to we're going to make a Unix socket, the, the family there is can, it's going to be a raw can socket and the type is can raw. And then we, you know, do this setup and address. Usually this would be like your IP address you're binding to and your report you're binding to. But now we need to like, make a socket can one, and we bind it. This is kind of ugly though. You don't want to do this every time you're writing something. So let's make a library. There's some other stuff that you need to do. And one of them that's kind of annoying is you got to pack and unpack the structs that socket can't expect, because socket can when it ends up working is there's a header file, it's got these structs defined for like a can frame, for example. And, you know, go doesn't interoperate that nicely with C structs. Unfortunately, Russ does it better. But hey, so you need to pack these up the right way and you done pack them the right way. You need to set some sock options, blah, blah, blah. You don't want to do this every time you write like a little script. So we make a library. And this makes it a lot easier. So what you end up doing is you just create a device and this is a raw interface. So suck can dot new run or face and you give it the that can if is a literally the string of the name, you know, can zero can one, whatever. And Joe's got this nice feature called defer, which stops you from leaving devices open by mistake. So you can say defer device got closed. And whenever that device goes out of scope, it'll call the close function and clean it up for you, which is great because I always forget to write those at the end of my functions. And then I end up with all these dangling file descriptors. And eventually, your OS goes, no, I won't let you create anymore. And then what you have is the ability to receive and send frames. So these are actually now Go structs and those fields that go struck to the RBID, the data length code and the data. And you just send receive those work with them as normal structs to all the sort of normal go things that you would do on them. And it's just makes a lot easier. Now, another thing that you might want to do is ISO TP, which is used for diagnostics and automotive, I won't get super into it. But the real quick explanation is can frames are eight bytes, you want to send more than eight bytes, there's a sort of higher level protocol that will let you send up to 4095 bytes in multiple frames. And yes, it also does this. So there is a kernel module called can ISO TP. Unfortunately, unlike other kernel modules for socket can, it is not typically built into the kernel or available on most distros. You need to, you know, go download it and build it yourself. It's really easy. It's like you get pull the thing and type make and then pseudo in smart. It's like three steps. But once you once you get that up and going, now you have inside the kernel the ability to do this chaining of messages so you can send larger buffers. That's nice because in the kernel, it's not in your application, meaning one, you don't write the code for it, which is awesome, you know, laziness is good. But also quite importantly, it's going to be faster because you don't have all the delays of stuff like going up to the application layer every frame and then like send it back down to happen in the kernel. Nice and quick. And this works very, very similarly. The difference is we now need to provide a RX and TX ID. So whenever you do ISOTP, you're going to be targeting a specific can ID and expecting data back on a specific can ID. So we answer those. We defer our device.close, which is the same thing. It's going to close down. And now instead of spending specific frames, we actually just send go byte arrays. So just an array of up to 4095 bytes. You shoot that out down the wire and it'll come back with those. If it sees a valid one, it will trigger the send buff. And this is, sorry, the receipt buff will actually complete. This is where it's very useful to have concurrency because you can sit in a go routine and wait for a buffer and maybe even receive a buffer and check some things to make sure it's actually the one that you want and it's got the right things. And then you can actually send it out. But you can be doing other things in the background while you're waiting for that and you're going to have timeouts and things like that. What's really convenient is you can do both these things at the same time. So you can have a raw interface and an ISOTP interface and you can send ISOTP data and then be receiving raw frames at the same time. You can have multiple raw interfaces if you wanted to. You can have multiple ISOTP interfaces that are listening and sending on different addresses. That's just handled by, you know, the Linux device or network device subsystem knows how to do that so you don't have to do it. You don't have to deal with all the synchronous accessing of the hardware. It's all just done for you. So that's really convenient. So let's just do a little demo. All the code for this is, in fact, online. And there's like this really hard problem of trying to make VMs. Sure, let's go full screen mode. VMs look sort of legible on a projector. And also my resolution is like, we're back in the 90s here with the plots. Cool. We'll roll with this. And actually, if we could, it's just be nice to you and set the background color to white. I think that will, well, white. Cool. Hopefully a little more contrast. So first off, we have tests, which we can run. I want to do that to be. So tests are nice. They actually test itself and make sure that can frames get sent and received and are in the right format. And it's actually doing this all using the, what's called the VCAN module. And that's a virtual CAN driver on socket CAN. So none of this has to leave my computer. I don't need an actual piece of hardware in CAN bus. I can just send it around inside the kernel. But all this would work and does work if you have an external device the exact same way. But it's just nice for testing because I don't want to plug in two CAN things and make a loop back and all that just to test my library. So some of the tools that are as examples in here, this window, it's going to be trouble. Two examples are a pretty simple implementation of CAN dump and CAN send. If you have an idea, like going there, you know, this is, I didn't count earlier. It's going to look awful on a projector, but it's like well under 100 lines code. Like it's like 30 lines code or something. And we can run CAN dump on interface. And what it's going to do is, VCAN 0. And we can do our typical, you know, run our system CAN send on VCAN 0 with 1, 2, 3, whatever. And it's, you know, working as you'd expect with a CAN dump tool. And it's not examples in there and there's a similar one for CAN send. What's also nice is we can use that ISOTP stuff and run the tests again. And we'll actually see ISOTP data fly back around. It's actually just loading up. So the first one that it's doing is a single. If you look at the tests, it'll tell you what they were. There was a RX-TX, a single frame and RX-TX a multi-frame. So the first one is a SF single frame and comes back. And then we do a first frame and we're going to send the full for 4,095 bytes of data. And we just have a buffer that goes up. And as you can see the SN there is the serial number of the frame. And it's going to keep, you know, first frame you have a flow control frame and after that you have all these consecutive frames for 4,095 bytes which goes on for a while and comes out. So if you're writing your own tools, writing something like a diagnostic tool, that's really handy. You don't need to deal with all that framing. You just put your UDS request together and send it and wait for one to come back. And all that's taken care of you by, taken care of by the kernel. And let's jump back here. I thought I had a slide about next steps in this thing. So I'll tell you, this is pretty proof of concepting now but I'm using it in some actual projects. So I'm going to keep, you know, contributing or making commits to the go stuff in here as I need features. There's some weirdness around how the ISOTP kernel module deals with some sock options for like, does it pad the frames out to 8 bytes? Does it, they did it in a weird way so I have to figure out how to make that work but that's all going to get done so that I can actually control it and you'll have a nice API rather than having to do these, you know, set sock ops with weird structs. So yeah, that's the idea there and it's just another option if you're trying to write CAN bus tools. You got some that does socket CAN or you want to play around with VCAN, your device. It's a way to play with it. I don't know how I'm doing on time. That was pretty quick but I'm having to take any questions or comments or whatever you like to do but thanks for coming and filling up the room. It's nice.