1

I am writing a network driver that should send packets to an Arduino using Serial communication. This is a homework assignment and this is only for educational purposes. Please, take that into account before suggesting that everything could be accomplished in user space.

This answer stated about filp_open and filp_close, and I thought that I could use them to open /dev/ttyACMx or /dev/ttyUSBx, but I read somewhere else that it is not a good idea to use I/O file operations inside the kernel, so I am looking for a better approach.

I have also read about outb and inb, but I have not found any way to get the port number argument required for both functions. I have tried using lsusb and writing to some of those 0xXX endpoint addresses but it did not work.

This is my transmit function, where I want to, instead of printing, writing to a serial port. My aux variable is just a union that contains two members: struct sk_buff skb and unsigned char bytes[sizeof(struct sk_buff)]. But at this point in the assignment, I just want to send the contents of skb.data to my Arduino serial.

aux = skb;
while(aux != NULL) {
    p.skb = *aux;
    for(i = 0; i < p.skb.len; i++) {
        if(i == 0) {
            printk(KERN_INFO "\\%02x", p.skb.data[i]);
        }
        else {
            printk(KERN_CONT "\\%02x", p.skb.data[i]);
        }

    }
    aux = aux->next;
}

And this is Arduino code is the following:

void setup() {
    Serial.begin(9600);
    Serial.println("Start");
}
void loop() {
    while(Serial.available() > 0)
        Serial.print(Serial.read());

    Serial.println();
}

It is simple as that. I want to read the content of a packet inside my Arduino. How can I write in a /dev/ttyACMx or /dev/ttyUSBx port inside my network driver?

alexandredias3d
  • 361
  • 3
  • 17
  • Neither File IO nor serial communication should happen directly in kernel mode. – datafiddler Nov 06 '18 at 14:19
  • I get why file I/O should not happen directly in the kernel, but can you elaborate on why I should avoid serial communication in kernel space? – alexandredias3d Nov 06 '18 at 15:09
  • in Arduino code: use `Serial.write(Serial.read);` and what for is the endless println()? – Juraj Nov 06 '18 at 18:39
  • @Juraj this is not the problem of my question. I just showed an example of how I want to read the data in the Arduino. My question is how to write on the serial in kernel space. – alexandredias3d Nov 06 '18 at 18:59
  • and it is not an answer – Juraj Nov 06 '18 at 19:01
  • You need a proxy driver that grabs exclusively one of the UARTs and provides a netlink layer on the other side. First what comes to my mind is a Bluetooth stack + corresponding hardware driver (*hci_uart*). And the enumeration of this entire scheme is platform dependent to some extent. – 0andriy Nov 06 '18 at 19:19
  • @0andriy Am I not allowed to just write the byte values on a specific port number using the [in*/out*](http://man7.org/linux/man-pages/man2/inb.2.html) functions? Also, I did not find much on this *proxy driver* concept that you mentioned. Aren't there more options other than the way you suggested? I believe that this would be extremely difficult to implement before the due date. Anyway, thanks for pointing this up! I have been struggling really hard with this homework. – alexandredias3d Nov 06 '18 at 21:47
  • Since you are asking such question, perhaps you need to start from the basics of multitasking OS architecture and some (high level) hardware design concepts. – 0andriy Nov 06 '18 at 22:03
  • Regarding proxy idea is just a possibility to make a bridge between two hardware related layers. There are quite rare cases when it’s needed in practice, but some cases can be done. For example, for networking layer it’s possible to provide a transport driver through UART media (like USB network, as an example). – 0andriy Nov 06 '18 at 22:07
  • You need something like SLIP, but implemented in kernel space https://superuser.com/questions/1295703/internet-connection-over-serial-port – 0andriy Nov 06 '18 at 22:12
  • @0andriy SLIP is already implemented in kernel space by the "slip" module. – Ian Abbott Nov 08 '18 at 16:56
  • @IanAbbott, AFAIU it needs to be expanded to cover asked question. Currently SLIP provides a netlink interface. So, from the question we know that OP is writing something like a network driver from one side with a possibilities to send something through UART. Either SLIP needs to be patched, or whatever OP has should export and use APIs from the SLIP module. – 0andriy Nov 08 '18 at 21:00
  • 1
    Forget about using `outb` and `inb` (or `readb` and `writeb`). That is only relevant for serial ports implemented by UARTs in port I/O (or memory-mapped I/O) space. Besides, the I/O addresses are probably already in use by a serial UART driver. From your question, it sounds like you want to access the Arduino board via some sort of USB serial device, but hooked into the kernel's network layer. – Ian Abbott Nov 09 '18 at 11:54
  • Personally, I'd just use the `filp_` functions, as that's probably what your teacher has in mind, unless your teacher expects you to implement the code as a TTY _line discipline_ (like the "slip" module does). – Ian Abbott Nov 09 '18 at 11:55
  • Sorry for the late reply. I didn't have the knowledge to build my own tty driver, so I started using the filp* functions. I will not accept the current answer because it uses the functions that I wanted to avoid. – alexandredias3d Dec 12 '18 at 20:45

1 Answers1

1

The reason why file IO is not recommended: file IO are blocking the file at the moment. Since you are opening the file in kernelspace, that would be a bad idea. Imagine that another process would like to open the same file.

On the otherhand, if you realy need to use file operations, filp_open / filp_close are the ones to use.

If your assignment doesn't specify what to use, please use the memory address to write to. It takes a lot of work (compared to file IO) to get your write/read operation to work, but it's a better approach. You don't block anything since you are writing to the address itself.

My advice: take some time, study your datasheet / memory map and write directly to the address. You will have to write a function for setting the direction of the register (write / read) and a function that reads the register or writes the register.

  • Should I use the ```outb``` and ```inb``` functions to write directly to the memory addresses? If so, how can I get the memory address that I should use to write? This [answer](https://stackoverflow.com/questions/47048726/baud-rate-of-inb-and-outb-commands-linux) for example, cites the address 0x3F8. How can I get the memory address of my Arduino? – alexandredias3d Nov 06 '18 at 15:05
  • It's not an answer. He needs actually a driver that proxies UART to the network layer/ – 0andriy Nov 06 '18 at 19:18