162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci.. include:: <isonum.txt>
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci============================
562306a36Sopenharmony_ciLinux Phonet protocol family
662306a36Sopenharmony_ci============================
762306a36Sopenharmony_ci
862306a36Sopenharmony_ciIntroduction
962306a36Sopenharmony_ci------------
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ciPhonet is a packet protocol used by Nokia cellular modems for both IPC
1262306a36Sopenharmony_ciand RPC. With the Linux Phonet socket family, Linux host processes can
1362306a36Sopenharmony_cireceive and send messages from/to the modem, or any other external
1462306a36Sopenharmony_cidevice attached to the modem. The modem takes care of routing.
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ciPhonet packets can be exchanged through various hardware connections
1762306a36Sopenharmony_cidepending on the device, such as:
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci  - USB with the CDC Phonet interface,
2062306a36Sopenharmony_ci  - infrared,
2162306a36Sopenharmony_ci  - Bluetooth,
2262306a36Sopenharmony_ci  - an RS232 serial port (with a dedicated "FBUS" line discipline),
2362306a36Sopenharmony_ci  - the SSI bus with some TI OMAP processors.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciPackets format
2762306a36Sopenharmony_ci--------------
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciPhonet packets have a common header as follows::
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci  struct phonethdr {
3262306a36Sopenharmony_ci    uint8_t  pn_media;  /* Media type (link-layer identifier) */
3362306a36Sopenharmony_ci    uint8_t  pn_rdev;   /* Receiver device ID */
3462306a36Sopenharmony_ci    uint8_t  pn_sdev;   /* Sender device ID */
3562306a36Sopenharmony_ci    uint8_t  pn_res;    /* Resource ID or function */
3662306a36Sopenharmony_ci    uint16_t pn_length; /* Big-endian message byte length (minus 6) */
3762306a36Sopenharmony_ci    uint8_t  pn_robj;   /* Receiver object ID */
3862306a36Sopenharmony_ci    uint8_t  pn_sobj;   /* Sender object ID */
3962306a36Sopenharmony_ci  };
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciOn Linux, the link-layer header includes the pn_media byte (see below).
4262306a36Sopenharmony_ciThe next 7 bytes are part of the network-layer header.
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciThe device ID is split: the 6 higher-order bits constitute the device
4562306a36Sopenharmony_ciaddress, while the 2 lower-order bits are used for multiplexing, as are
4662306a36Sopenharmony_cithe 8-bit object identifiers. As such, Phonet can be considered as a
4762306a36Sopenharmony_cinetwork layer with 6 bits of address space and 10 bits for transport
4862306a36Sopenharmony_ciprotocol (much like port numbers in IP world).
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciThe modem always has address number zero. All other device have a their
5162306a36Sopenharmony_ciown 6-bit address.
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciLink layer
5562306a36Sopenharmony_ci----------
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciPhonet links are always point-to-point links. The link layer header
5862306a36Sopenharmony_ciconsists of a single Phonet media type byte. It uniquely identifies the
5962306a36Sopenharmony_cilink through which the packet is transmitted, from the modem's
6062306a36Sopenharmony_ciperspective. Each Phonet network device shall prepend and set the media
6162306a36Sopenharmony_citype byte as appropriate. For convenience, a common phonet_header_ops
6262306a36Sopenharmony_cilink-layer header operations structure is provided. It sets the
6362306a36Sopenharmony_cimedia type according to the network device hardware address.
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciLinux Phonet network interfaces support a dedicated link layer packets
6662306a36Sopenharmony_citype (ETH_P_PHONET) which is out of the Ethernet type range. They can
6762306a36Sopenharmony_cionly send and receive Phonet packets.
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciThe virtual TUN tunnel device driver can also be used for Phonet. This
7062306a36Sopenharmony_cirequires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case,
7162306a36Sopenharmony_cithere is no link-layer header, so there is no Phonet media type byte.
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciNote that Phonet interfaces are not allowed to re-order packets, so
7462306a36Sopenharmony_cionly the (default) Linux FIFO qdisc should be used with them.
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciNetwork layer
7862306a36Sopenharmony_ci-------------
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ciThe Phonet socket address family maps the Phonet packet header::
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci  struct sockaddr_pn {
8362306a36Sopenharmony_ci    sa_family_t spn_family;    /* AF_PHONET */
8462306a36Sopenharmony_ci    uint8_t     spn_obj;       /* Object ID */
8562306a36Sopenharmony_ci    uint8_t     spn_dev;       /* Device ID */
8662306a36Sopenharmony_ci    uint8_t     spn_resource;  /* Resource or function */
8762306a36Sopenharmony_ci    uint8_t     spn_zero[...]; /* Padding */
8862306a36Sopenharmony_ci  };
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciThe resource field is only used when sending and receiving;
9162306a36Sopenharmony_ciIt is ignored by bind() and getsockname().
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciLow-level datagram protocol
9562306a36Sopenharmony_ci---------------------------
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ciApplications can send Phonet messages using the Phonet datagram socket
9862306a36Sopenharmony_ciprotocol from the PF_PHONET family. Each socket is bound to one of the
9962306a36Sopenharmony_ci2^10 object IDs available, and can send and receive packets with any
10062306a36Sopenharmony_ciother peer.
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci::
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci  struct sockaddr_pn addr = { .spn_family = AF_PHONET, };
10562306a36Sopenharmony_ci  ssize_t len;
10662306a36Sopenharmony_ci  socklen_t addrlen = sizeof(addr);
10762306a36Sopenharmony_ci  int fd;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci  fd = socket(PF_PHONET, SOCK_DGRAM, 0);
11062306a36Sopenharmony_ci  bind(fd, (struct sockaddr *)&addr, sizeof(addr));
11162306a36Sopenharmony_ci  /* ... */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci  sendto(fd, msg, msglen, 0, (struct sockaddr *)&addr, sizeof(addr));
11462306a36Sopenharmony_ci  len = recvfrom(fd, buf, sizeof(buf), 0,
11562306a36Sopenharmony_ci		 (struct sockaddr *)&addr, &addrlen);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciThis protocol follows the SOCK_DGRAM connection-less semantics.
11862306a36Sopenharmony_ciHowever, connect() and getpeername() are not supported, as they did
11962306a36Sopenharmony_cinot seem useful with Phonet usages (could be added easily).
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciResource subscription
12362306a36Sopenharmony_ci---------------------
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ciA Phonet datagram socket can be subscribed to any number of 8-bits
12662306a36Sopenharmony_ciPhonet resources, as follow::
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci  uint32_t res = 0xXX;
12962306a36Sopenharmony_ci  ioctl(fd, SIOCPNADDRESOURCE, &res);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciSubscription is similarly cancelled using the SIOCPNDELRESOURCE I/O
13262306a36Sopenharmony_cicontrol request, or when the socket is closed.
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ciNote that no more than one socket can be subscribed to any given
13562306a36Sopenharmony_ciresource at a time. If not, ioctl() will return EBUSY.
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ciPhonet Pipe protocol
13962306a36Sopenharmony_ci--------------------
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ciThe Phonet Pipe protocol is a simple sequenced packets protocol
14262306a36Sopenharmony_ciwith end-to-end congestion control. It uses the passive listening
14362306a36Sopenharmony_cisocket paradigm. The listening socket is bound to an unique free object
14462306a36Sopenharmony_ciID. Each listening socket can handle up to 255 simultaneous
14562306a36Sopenharmony_ciconnections, one per accept()'d socket.
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci::
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci  int lfd, cfd;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci  lfd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE);
15262306a36Sopenharmony_ci  listen (lfd, INT_MAX);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci  /* ... */
15562306a36Sopenharmony_ci  cfd = accept(lfd, NULL, NULL);
15662306a36Sopenharmony_ci  for (;;)
15762306a36Sopenharmony_ci  {
15862306a36Sopenharmony_ci    char buf[...];
15962306a36Sopenharmony_ci    ssize_t len = read(cfd, buf, sizeof(buf));
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci    /* ... */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci    write(cfd, msg, msglen);
16462306a36Sopenharmony_ci  }
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciConnections are traditionally established between two endpoints by a
16762306a36Sopenharmony_ci"third party" application. This means that both endpoints are passive.
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ciAs of Linux kernel version 2.6.39, it is also possible to connect
17162306a36Sopenharmony_citwo endpoints directly, using connect() on the active side. This is
17262306a36Sopenharmony_ciintended to support the newer Nokia Wireless Modem API, as found in
17362306a36Sopenharmony_cie.g. the Nokia Slim Modem in the ST-Ericsson U8500 platform::
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci  struct sockaddr_spn spn;
17662306a36Sopenharmony_ci  int fd;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci  fd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE);
17962306a36Sopenharmony_ci  memset(&spn, 0, sizeof(spn));
18062306a36Sopenharmony_ci  spn.spn_family = AF_PHONET;
18162306a36Sopenharmony_ci  spn.spn_obj = ...;
18262306a36Sopenharmony_ci  spn.spn_dev = ...;
18362306a36Sopenharmony_ci  spn.spn_resource = 0xD9;
18462306a36Sopenharmony_ci  connect(fd, (struct sockaddr *)&spn, sizeof(spn));
18562306a36Sopenharmony_ci  /* normal I/O here ... */
18662306a36Sopenharmony_ci  close(fd);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci.. Warning:
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci   When polling a connected pipe socket for writability, there is an
19262306a36Sopenharmony_ci   intrinsic race condition whereby writability might be lost between the
19362306a36Sopenharmony_ci   polling and the writing system calls. In this case, the socket will
19462306a36Sopenharmony_ci   block until write becomes possible again, unless non-blocking mode
19562306a36Sopenharmony_ci   is enabled.
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ciThe pipe protocol provides two socket options at the SOL_PNPIPE level:
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci  PNPIPE_ENCAP accepts one integer value (int) of:
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci    PNPIPE_ENCAP_NONE:
20362306a36Sopenharmony_ci      The socket operates normally (default).
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci    PNPIPE_ENCAP_IP:
20662306a36Sopenharmony_ci      The socket is used as a backend for a virtual IP
20762306a36Sopenharmony_ci      interface. This requires CAP_NET_ADMIN capability. GPRS data
20862306a36Sopenharmony_ci      support on Nokia modems can use this. Note that the socket cannot
20962306a36Sopenharmony_ci      be reliably poll()'d or read() from while in this mode.
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci  PNPIPE_IFINDEX
21262306a36Sopenharmony_ci      is a read-only integer value. It contains the
21362306a36Sopenharmony_ci      interface index of the network interface created by PNPIPE_ENCAP,
21462306a36Sopenharmony_ci      or zero if encapsulation is off.
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci  PNPIPE_HANDLE
21762306a36Sopenharmony_ci      is a read-only integer value. It contains the underlying
21862306a36Sopenharmony_ci      identifier ("pipe handle") of the pipe. This is only defined for
21962306a36Sopenharmony_ci      socket descriptors that are already connected or being connected.
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ciAuthors
22362306a36Sopenharmony_ci-------
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ciLinux Phonet was initially written by Sakari Ailus.
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ciOther contributors include Mikä Liljeberg, Andras Domokos,
22862306a36Sopenharmony_ciCarlos Chinea and Rémi Denis-Courmont.
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciCopyright |copy| 2008 Nokia Corporation.
231