LCOV - code coverage report
Current view: top level - zephyr/net - midi2.h Coverage Total Hit
Test: new.info Lines: 87.8 % 41 36
Test Date: 2025-10-20 12:20:01

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2025 Titouan Christophe
       3              :  * SPDX-License-Identifier: Apache-2.0
       4              :  */
       5              : 
       6              : #ifndef ZEPHYR_INCLUDE_NET_MIDI2_H_
       7              : #define ZEPHYR_INCLUDE_NET_MIDI2_H_
       8              : 
       9              : /**
      10              :  * @defgroup net_midi2 Network MIDI 2.0
      11              :  * @since 4.3
      12              :  * @version 0.1.0
      13              :  * @ingroup networking
      14              :  * @{
      15              :  */
      16              : 
      17              : /**
      18              :  * @defgroup netmidi10 User Datagram Protocol for Universal MIDI Packets
      19              :  * @ingroup net_midi2
      20              :  * @{
      21              :  * @details Definitions based on the following document
      22              :  * <a href="https://midi.org/network-midi-2-0">
      23              :  * User Datagram Protocol for Universal MIDI Packets
      24              :  * Network MIDI 2.0 (UDP) Transport Specification - Document version 1.0
      25              :  * (MIDI Association Document: M2-124-UM)
      26              :  * </a>
      27              :  * @}
      28              :  */
      29              : 
      30              : 
      31              : #include <stdint.h>
      32              : #include <zephyr/audio/midi.h>
      33              : #include <zephyr/net/socket.h>
      34              : #include <zephyr/posix/poll.h>
      35              : 
      36              : /**
      37              :  * Size, in bytes, of the nonce sent to the client for authentication
      38              :  * @see netmidi10: 6.7 Invitation Reply: Authentication Required
      39              :  */
      40            1 : #define NETMIDI2_NONCE_SIZE  16
      41              : 
      42              : /**
      43              :  * @brief      Statically declare a Network (UDP) MIDI 2.0 endpoint host
      44              :  * @param      _var_name  The name of the variable holding the server data
      45              :  * @param      _ep_name   The UMP endpoint name
      46              :  * @param      _piid      The UMP Product Instance ID. If NULL,
      47              :  *                        HWINFO device ID will be used at runtime.
      48              :  * @param      _port      The UDP port to listen to, or 0 for automatic assignment
      49              :  */
      50            1 : #define NETMIDI2_EP_DEFINE(_var_name, _ep_name, _piid, _port) \
      51              :         static struct netmidi2_ep _var_name = { \
      52              :                 .name = (_ep_name), \
      53              :                 .piid = (_piid), \
      54              :                 .addr4.sin_port = (_port), \
      55              :                 .auth_type = NETMIDI2_AUTH_NONE, \
      56              :         }
      57              : 
      58              : /**
      59              :  * @brief      Statically declare a Network (UDP) MIDI 2.0 endpoint host,
      60              :  *             with a predefined shared secret key for authentication
      61              :  * @param      _var_name  The name of the variable holding the server data
      62              :  * @param      _ep_name   The UMP endpoint name
      63              :  * @param      _piid      The UMP Product Instance ID. If NULL,
      64              :  *                        HWINFO device ID will be used at runtime.
      65              :  * @param      _port      The UDP port to listen to, or 0 for automatic assignment
      66              :  * @param      _secret    The shared secret key clients must provide to connect
      67              :  */
      68            1 : #define NETMIDI2_EP_DEFINE_WITH_AUTH(_var_name, _ep_name, _piid, _port, _secret) \
      69              :         static struct netmidi2_ep _var_name = { \
      70              :                 .name = (_ep_name), \
      71              :                 .piid = (_piid), \
      72              :                 .addr4.sin_port = (_port), \
      73              :                 .auth_type = NETMIDI2_AUTH_SHARED_SECRET, \
      74              :                 .shared_auth_secret = (_secret), \
      75              :         }
      76              : 
      77              : /**
      78              :  * @brief      Statically declare a Network (UDP) MIDI 2.0 endpoint host,
      79              :  *             with a predefined list of users/passwords for authentication
      80              :  * @param      _var_name  The name of the variable holding the server data
      81              :  * @param      _ep_name   The UMP endpoint name
      82              :  * @param      _piid      The UMP Product Instance ID. If NULL,
      83              :  *                        HWINFO device ID will be used at runtime.
      84              :  * @param      _port      The UDP port to listen to, or 0 for automatic assignment
      85              :  * @param      ...        The username/password pairs (struct netmidi2_user)
      86              :  *
      87              :  * Example usage:
      88              :  * @code
      89              :  * NETMIDI2_EP_DEFINE_WITH_USERS(my_server, "endpoint", NULL, 0,
      90              :  *                                {.name="user1", .password="passwd1"},
      91              :  *                                {.name="user2", .password="passwd2"})
      92              :  * @endcode
      93              :  */
      94            1 : #define NETMIDI2_EP_DEFINE_WITH_USERS(_var_name, _ep_name, _piid, _port, ...) \
      95              :         static const struct netmidi2_userlist users_of_##_var_name = { \
      96              :                 .n_users = ARRAY_SIZE(((struct netmidi2_user []) { __VA_ARGS__ })), \
      97              :                 .users = { __VA_ARGS__ }, \
      98              :         }; \
      99              :         static struct netmidi2_ep _var_name = { \
     100              :                 .name = (_ep_name), \
     101              :                 .piid = (_piid), \
     102              :                 .addr4.sin_port = (_port), \
     103              :                 .auth_type = NETMIDI2_AUTH_USER_PASSWORD, \
     104              :                 .userlist = &users_of_##_var_name, \
     105              :         }
     106              : 
     107              : struct netmidi2_ep;
     108              : 
     109              : /**
     110              :  * @brief      A username/password pair for user-based authentication
     111              :  */
     112            1 : struct netmidi2_user {
     113              :         /** The user name for authentication */
     114            1 :         const char *name;
     115              :         /** The password for authentication */
     116            1 :         const char *password;
     117              : };
     118              : 
     119              : /**
     120              :  * @brief      A list of users for user-based authentication
     121              :  */
     122            1 : struct netmidi2_userlist {
     123              :         /** Number of users in the list */
     124            1 :         size_t n_users;
     125              :         /** The user/password pairs */
     126            1 :         const struct netmidi2_user users[];
     127              : };
     128              : 
     129              : /**
     130              :  * @brief      A Network MIDI2 session, representing a connection to a peer
     131              :  */
     132            1 : struct netmidi2_session {
     133              :         /**
     134              :          * State of this session
     135              :          * @see netmidi10: 6.1 Session States
     136              :          */
     137            1 :         enum {
     138              :                 /** The session is not in use */
     139              :                 NETMIDI2_SESSION_NOT_INITIALIZED = 0,
     140              :                 /** Device may be aware of each other (e.g. through mDNS),
     141              :                  *  however neither device has sent an Invitation.
     142              :                  *  The two Devices are not in a Session.
     143              :                  */
     144              :                 NETMIDI2_SESSION_IDLE,
     145              :                 /** Client has sent Invitation, however the Host has not
     146              :                  *  accepted the Invitation. A Bye Command has not been
     147              :                  *  sent or received.
     148              :                  */
     149              :                 NETMIDI2_SESSION_PENDING_INVITATION,
     150              :                 /** Host has replied with Invitation Reply: Authentication
     151              :                  *  Required or Invitation Reply: User Authentication Required.
     152              :                  *  No timeout has yet occurred. This state is different from
     153              :                  * Idle, because the Client and Host need to store the Nonce.
     154              :                  */
     155              :                 NETMIDI2_SESSION_AUTH_REQUIRED,
     156              :                 /** Invitation accepted, UMP Commands can be exchanged. */
     157              :                 NETMIDI2_SESSION_ESTABLISHED,
     158              :                 /** One Device has sent the Session Reset Command and is
     159              :                  *  waiting for Session Reset Reply, and a timeout has not
     160              :                  *  yet occurred.
     161              :                  */
     162              :                 NETMIDI2_SESSION_PENDING_RESET,
     163              :                 /** one Endpoint has sent Bye and is waiting for Bye Reply,
     164              :                  *  and a timeout has not yet occurred.
     165              :                  */
     166              :                 NETMIDI2_SESSION_PENDING_BYE,
     167            1 :         } state;
     168              :         /** Sequence number of the next universal MIDI packet to send */
     169            1 :         uint16_t tx_ump_seq;
     170              :         /** Sequence number of the next universal MIDI packet to receive */
     171            1 :         uint16_t rx_ump_seq;
     172              :         /** Remote address of the peer */
     173            1 :         struct sockaddr_storage addr;
     174              :         /** Length of the peer's remote address */
     175            1 :         socklen_t addr_len;
     176              :         /** The Network MIDI2 endpoint to which this session belongs */
     177            1 :         struct netmidi2_ep *ep;
     178              : #if defined(CONFIG_NETMIDI2_HOST_AUTH) || defined(__DOXYGEN__)
     179              :         /** The username to which this session belongs */
     180            1 :         const struct netmidi2_user *user;
     181              :         /** The crypto nonce used to authorize this session */
     182            1 :         char nonce[NETMIDI2_NONCE_SIZE];
     183              : #endif
     184              :         /** The transmission buffer for that peer */
     185            1 :         struct net_buf *tx_buf;
     186              :         /** The transmission work for that peer */
     187            1 :         struct k_work tx_work;
     188              : };
     189              : 
     190              : /**
     191              :  * @brief      Type of authentication in Network MIDI2
     192              :  */
     193            1 : enum netmidi2_auth_type {
     194              :         /** No authentication required */
     195              :         NETMIDI2_AUTH_NONE,
     196              :         /** Authentication with a shared secret key */
     197              :         NETMIDI2_AUTH_SHARED_SECRET,
     198              :         /** Authentication with username and password */
     199              :         NETMIDI2_AUTH_USER_PASSWORD,
     200              : };
     201              : 
     202              : /**
     203              :  * @brief      A Network MIDI2.0 Endpoint
     204              :  */
     205            1 : struct netmidi2_ep {
     206              :         /** The endpoint name */
     207            1 :         const char *name;
     208              :         /** The endpoint product instance id */
     209            1 :         const char *piid;
     210              :         /** The local endpoint address */
     211              :         union {
     212            0 :                 struct sockaddr addr;
     213            0 :                 struct sockaddr_in addr4;
     214            0 :                 struct sockaddr_in6 addr6;
     215            1 :         };
     216              :         /** The listening socket wrapped in a poll descriptor */
     217            1 :         struct pollfd pollsock;
     218              :         /** The function to call when data is received from a client */
     219            1 :         void (*rx_packet_cb)(struct netmidi2_session *session,
     220              :                              const struct midi_ump ump);
     221              :         /** List of peers to this endpoint */
     222            1 :         struct netmidi2_session peers[CONFIG_NETMIDI2_HOST_MAX_CLIENTS];
     223              :         /** The type of authentication required to establish a session
     224              :          *  with this host endpoint
     225              :          */
     226            1 :         enum netmidi2_auth_type auth_type;
     227              : #if defined(CONFIG_NETMIDI2_HOST_AUTH) || defined(__DOXYGEN__)
     228              :         union {
     229              :                 /** A shared authentication key */
     230            1 :                 const char *shared_auth_secret;
     231              :                 /** A list of users/passwords */
     232            1 :                 const struct netmidi2_userlist *userlist;
     233            0 :         };
     234              : #endif
     235              : };
     236              : 
     237              : /**
     238              :  * @brief      Start hosting a network (UDP) Universal MIDI Packet endpoint
     239              :  * @param      ep    The network endpoint to start
     240              :  * @return     0 on success, -errno on error
     241              :  */
     242            1 : int netmidi2_host_ep_start(struct netmidi2_ep *ep);
     243              : 
     244              : /**
     245              :  * @brief      Send a Universal MIDI Packet to all clients connected to the endpoint
     246              :  * @param      ep    The endpoint
     247              :  * @param[in]  ump   The packet to send
     248              :  */
     249            1 : void netmidi2_broadcast(struct netmidi2_ep *ep, const struct midi_ump ump);
     250              : 
     251              : /**
     252              :  * @brief      Send a Universal MIDI Packet to a single client
     253              :  * @param      sess  The session identifying the single client
     254              :  * @param[in]  ump   The packet to send
     255              :  */
     256            1 : void netmidi2_send(struct netmidi2_session *sess, const struct midi_ump ump);
     257              : 
     258              : /** @} */
     259              : 
     260              : #endif
        

Generated by: LCOV version 2.0-1