Connectivity

The SoC component of the software consists of trusted and untrusted software. Untrusted software has less privileges and thus a reduced view of peripherals and memory.

Sockets in general

The Ganymed offers a socket implementation which is very similar to the one found on Unix systems. Sockets can be used to start connections via ethernet, WiFi, Bluetooth, CAN or UART. Let us walk through the process of creating a socket.

The first thing you need to to is to create a socket. You need to use the function usoc_socket to do so. Let us take look at the function and its parameters.

int main() {
  usoc_socket_t usoc_socket(domain, type, protocol);

  if (socket == NULL) {
    usoc_printf("Creation of socket failed\n");
    return;
  }
}

As you can see, the function gets three parameters domain, type and protocol.

The domain is one of USOC_INET_LAN, USOC_INET_WIFI, USOC_BT, USOC_CAN or USOC_UART. As you can see by the enum value names, this is the place to decide over the hardware interface to be used.

The type parameter only supports one value which is always USOC_TYPE_STREAM.

The parameter protocol is one of USOC_PROTO_TCP, USOC_PROTO_UDP or USOC_PROTO_NONE. As you can easily see by the enum value names, here you can device, which protocol to use.

The function returns a handler to a socket, if the creation was successful, a value of NULL otherwise.

The next step is a call to the function usoc_socket_connect. The function gets two parameters. The first one is the socket handler that you just created. The second one depends on the type of socket. The following tutorials will explain the details of the parameter depending on the different socket types. For now, let us just stick with a mysterious undefined variable named config.

If the conenction attempt succeeds, the function will return a value of USOC_SOCK_ERR_NONE.

int main() {
  usoc_socket_t usoc_socket(domain, type, protocol);

  if (socket == NULL) {
    usoc_printf("Creation of socket failed\n");
    return;
  }

  if(usoc_socket_connect(socket, &config) != USOC_SOCK_ERR_NONE)
  {
    usoc_printf("Connection to server of socket failed\n");
    return;
  }
}

After a successful connection, we are ready to write and read from the socket. In this example, we send a zero terminated "Hello World" string and expect to receive some bytes in return. While the first three parameters should be pretty self explanatory, the last one is flags. As for now, there are no flags supported and thus this parameter is always zero.

int main() {
  usoc_socket_t usoc_socket(domain, type, protocol);

  if (socket == NULL) {
    usoc_printf("Creation of socket failed\n");
    return;
  }

  if(usoc_socket_connect(socket, &config) != USOC_SOCK_ERR_NONE)
  {
    usoc_printf("Connection to server of socket failed\n");
    return;
  }

  uint8_t buffer[] = "Hello World";

  int32_t size = usoc_socket_write(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes written\n");
  }

  size = usoc_socket_read(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes read\n");
  }
}

The last thing to do now is to close the socket again.

int main() {
  usoc_socket_t usoc_socket(domain, type, protocol);

  if (socket == NULL) {
    usoc_printf("Creation of socket failed\n");
    return;
  }

  if(usoc_socket_connect(socket, &config) != USOC_SOCK_ERR_NONE)
  {
    usoc_printf("Connection to server of socket failed\n");
    return;
  }

  uint8_t buffer[] = "Hello World";

  int32_t size = usoc_socket_write(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes written\n");
  }

  size = usoc_socket_read(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes read\n");
  }

  usoc_socket_close(socket);
}

That is it for the general socket tutorial. You are now ready to look into the different config variables that we mysteriously did not define in this tutorial.

Wi-Fi

In this WiFi tutorial, we will fill in the gaps from the general sockets tutorial. If you have not read it, go back to it and do so.

Let us start!

Before we can start to fill in the gaps that the sockets tutorial left, we need to add an additional step, which is, starting WiFi hardware interface. You can do so by using the function usoc_interface_up. It takes a usoc_interface_t for which we will choose the enumerated value USOC_IFACE_WIFI. It returns a usoc_interface_error_t typed result, which we want to be USOC_IFACE_ERR_NONE.

Additionally, you need to setup the WiFi SSID and password to which to connect to. Declare the two values in global variables named ssid and pwd inside of the file link_usoc_user_config_default.c respectively. The Ganymed SDK will pick them up and use them while bringing up the WiFi interface.

At the end of our program, we shut the WiFi interface down by using the function usoc_interface_down.

#include "usoc_user_services.h"
#include "usoc_interface_API.h"

// Put these lines into your link_usoc_user_config_default.c file
const char ssid[] = { "MySsid" };
const char pwd[] = { "MyPassword" };

int main() {
  if (usoc_interface_up(USOC_IFACE_WIFI) == USOC_IFACE_ERR_NONE) {
    usoc_printf("Wi-Fi init successful\n");
  } 
  else {
    usoc_printf("Wi-Fi init failed\n");
  }

  if (usoc_interface_down(USOC_IFACE_WIFI) == USOC_IFACE_ERR_NONE) {
    usoc_printf("Wi-Fi deinit successful\n");
  } 
  else {
    usoc_printf("Wi-Fi deinit failed\n");
  }
}

Now that the WiFi interface is up and running, we can create a client socket to a listening server over the WiFi interface.

Take a look at the used enumerated values that we have put into usoc_socket. We defined to use the USOC_INET_WIFI interface, using a USOC_TYPE_STREAM protocol which is the USOC_PROTO_TCP one.

Then we are using the struct usoc_inet_wifi_config_t to setup the IP address and the port of the server to which we want to connect to.

The rest of the socket functionality can be used in the same as described in the general socket tutorial.

#include <stdint.h>
#include "usoc_user_services.h"
#include "usoc_socket.h"

// Put these lines into your link_usoc_user_config_default.c file
const char ssid[] = { "MySsid" };
const char pwd[] = { "MyPassword" };

int main() {
    if (usoc_interface_up(USOC_IFACE_WIFI) == USOC_IFACE_ERR_NONE) {
        usoc_printf("Wi-Fi init successful\n");
    } 
    else {
        usoc_printf("Wi-Fi init failed\n");
    }

    usoc_socket_t socket = usoc_socket(USOC_INET_WIFI, USOC_TYPE_STREAM, USOC_PROTO_TCP);
    if(socket == NULL) {
        usoc_printf("Creation of socket failed\n");
        return;
    }

    usoc_inet_wifi_config_t server_address = {.address = "192.168.0.59", .port = 4660};

    if(usoc_socket_connect(socket, &server_address) != USOC_SOCK_ERR_NONE)
    {
        usoc_printf("Connection to server of socket failed\n");
        return;
    }

    uint8_t buffer[] = "Hello World";

    int32_t size = usoc_socket_write(socket, buffer, size_of(buffer), 0);
  
    if(size > 0) {
        usoc_printf("%i bytes written\n");
    }
  
    size = usoc_socket_read(socket, buffer, size_of(buffer), 0);
  
    if(size > 0) {
        usoc_printf("%i bytes read\n");
    }
  
    usoc_socket_close(socket);

    if (usoc_interface_down(USOC_IFACE_WIFI) == USOC_IFACE_ERR_NONE) {
      usoc_printf("Wi-Fi deinit successful\n");
    } 
    else {
      usoc_printf("Wi-Fi deinit failed\n");
    }  
}

LAN

In this LAN tutorial, we will fill in the gaps from the general sockets tutorial. If you have not read it, go back to it and do so.

Let us start!

Before you can retreive a LAN socket, you need to start the LAN interface. We use the function usoc_interface_up for it. It can be parameterized with the global variables ucIPAddress, ucNetMask and ucGatewayAddress, which are defined in your link_usoc_user_config_default.c.

After using the LAN connection, you can shut it down with usoc_interface_down.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

// Put these lines into your link_usoc_user_config_default.c file
const uint8_t ucIPAddress[ 4 ] = { 192, 168, 178, 200 };
const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 0 };
const uint8_t ucGatewayAddress[ 4 ] = { 192, 168, 178, 1 };

int main() {
  if (usoc_interface_up(USOC_IFACE_LAN) == USOC_IFACE_ERR_NONE) {
    usoc_printf("LAN init successful\n");
  } 
  else {
    usoc_printf("LAN init failed\n");
  }

  if (usoc_interface_down(USOC_IFACE_LAN) == USOC_IFACE_ERR_NONE) {
    usoc_printf("LAN deinit successful\n");
  } 
  else {
    usoc_printf("LAN deinit failed\n");
  }
}

Now that we have have started the LAN interface, we can make a connection to a server.

The function usoc_socket_connect is give a usoc_inet_LAN_config_t struct as a parameter. It allows to set the IP address and the port of the destination.

The rest of the socket functionality can be used in the same as described in the general socket tutorial.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

// Put these lines into your link_usoc_user_config_default.c file
const uint8_t ucIPAddress[ 4 ] = { 192, 168, 178, 200 };
const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 0 };
const uint8_t ucGatewayAddress[ 4 ] = { 192, 168, 178, 1 };

int main() {
  if (usoc_interface_up(USOC_IFACE_LAN) == USOC_IFACE_ERR_NONE) {
    usoc_printf("LAN init successful\n");
  } 
  else {
    usoc_printf("LAN init failed\n");
  }

  usoc_socket_t socket = (USOC_INET_LAN, USOC_TYPE_STREAM, USOC_PROTO_TCP);
  if(socket == NULL) {
    usoc_printf("Creation of socket failed\n");
    return;
  }

  usoc_inet_LAN_config_t server_address = {.address = "192.168.0.59", .port = 4660};

  if(usoc_socket_connect(socket, &server_address) != USOC_SOCK_ERR_NONE)
  {
    usoc_printf("Connection to server of socket failed\n");
    return;
  }

  uint8_t buffer[] = "Hello World";

  int32_t size = usoc_socket_write(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes written\n");
  }

  size = usoc_socket_read(socket, buffer, size_of(buffer), 0);

  if(size > 0) {
      usoc_printf("%i bytes read\n");
  }

  usoc_socket_close(socket);

  if (usoc_interface_down(USOC_IFACE_LAN) == USOC_IFACE_ERR_NONE) {
    usoc_printf("LAN deinit successful\n");
  } 
  else {
    usoc_printf("LAN deinit failed\n");
  }
}

Bluetooth

In this Bluetooth tutorial, we will fill in the gaps from the general sockets tutorial. If you have not read it, go back to it and do so.

Let us start!

Bluetooth is a short-range wireless technology standard for exchanging data between fixed and mobile devices over short distances.

If we want to use it, we need to start the Bluetooth interface first. We use the function usoc_interface_up for this. In contrast to LAN or WiFi, there are no parameters that can be used to configure the interface.

After we are done with it, we shut it down by using the function usoc_interface_down.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

int main {
  if (usoc_interface_up(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT init successful\n");
  } 
  else {
    usoc_printf("BT init failed\n");
  }

  if (usoc_interface_down(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT deinit successful\n");
  } 
  else {
    usoc_printf("BT deinit failed\n");
  }
}

Now that Bluetooth is up and running, we can start to use it. At first we need a socket. Use the already known function usoc_socket. Since Bluetooth does not use TCP or UDP, the sock_protocol parameter has to be set to USOC_PROTO_NONE.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

int main {
  if (usoc_interface_up(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT init successful\n");
  } 
  else {
    usoc_printf("BT init failed\n");
  }

  usoc_socket_t client = usoc_socket(USOC_BT, USOC_TYPE_STREAM, USOC_PROTO_NONE);

  if (usoc_interface_down(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT deinit successful\n");
  } 
  else {
    usoc_printf("BT deinit failed\n");
  }
}

To connect to an Bluetooth device, we use usoc_socket_connect with a usoc_bt_config_t type paramter. There, we need to set an address. It is the Bluetooth address, which is a 48 bit value that uniquely identifies a Bluetooth device. It can look like 64:80:99:AD:F2:36. Find out that address of the Bluetooth device that you want the Ganymed to connect to.

Do not forget to enable Bluetooth on the device you want to connect to.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

int main {
  if (usoc_interface_up(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT init successful\n");
  } 
  else {
    usoc_printf("BT init failed\n");
  }

  usoc_socket_t client = usoc_socket(USOC_BT, USOC_TYPE_STREAM, USOC_PROTO_NONE);

  usoc_bt_config_t device;
  device.address = "64:80:99:AD:F2:36";

  if (usoc_socket_connect(client, &device) != USOC_SOCK_ERR_NONE) {
    usoc_printf("Unable to connect to remote device\n");
    return;
  }

  usoc_printf("Connected to remote device\n");

  if (usoc_interface_down(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT deinit successful\n");
  } 
  else {
    usoc_printf("BT deinit failed\n");
  }
}

Now that we are connected, we can finally write and read bytes from an to the socket, as described in the general socket tutorial.

#include "usoc_interface_API.h"
#include "usoc_user_services.h"
#include "usoc_socket.h"

int main {
  if (usoc_interface_up(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT init successful\n");
  } 
  else {
    usoc_printf("BT init failed\n");
  }

  usoc_socket_t client = usoc_socket(USOC_BT, USOC_TYPE_STREAM, USOC_PROTO_NONE);

  usoc_bt_config_t device;
  device.address = "64:80:99:AD:F2:36";

  if (usoc_socket_connect(client, &device) != USOC_SOCK_ERR_NONE) {
    usoc_printf("Unable to connect to remote device\n");
    return;
  }

  usoc_printf("Connected to remote device\n");

  if (usoc_interface_down(USOC_IFACE_BT) == USOC_IFACE_ERR_NONE) {
    usoc_printf("BT deinit successful\n");
  } 
  else {
    usoc_printf("BT deinit failed\n");
  }
}

Beware that Bluetooth does not use an IP based protocol. Therefore, you cannot bind a socket to a port.