Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | .. include:: <isonum.txt> |
| 3 | |
| 4 | ============================ |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 5 | Linux Phonet protocol family |
| 6 | ============================ |
| 7 | |
| 8 | Introduction |
| 9 | ------------ |
| 10 | |
| 11 | Phonet is a packet protocol used by Nokia cellular modems for both IPC |
| 12 | and RPC. With the Linux Phonet socket family, Linux host processes can |
| 13 | receive and send messages from/to the modem, or any other external |
| 14 | device attached to the modem. The modem takes care of routing. |
| 15 | |
| 16 | Phonet packets can be exchanged through various hardware connections |
| 17 | depending on the device, such as: |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 18 | |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 19 | - USB with the CDC Phonet interface, |
| 20 | - infrared, |
| 21 | - Bluetooth, |
| 22 | - an RS232 serial port (with a dedicated "FBUS" line discipline), |
| 23 | - the SSI bus with some TI OMAP processors. |
| 24 | |
| 25 | |
| 26 | Packets format |
| 27 | -------------- |
| 28 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 29 | Phonet packets have a common header as follows:: |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 30 | |
| 31 | struct phonethdr { |
| 32 | uint8_t pn_media; /* Media type (link-layer identifier) */ |
| 33 | uint8_t pn_rdev; /* Receiver device ID */ |
| 34 | uint8_t pn_sdev; /* Sender device ID */ |
| 35 | uint8_t pn_res; /* Resource ID or function */ |
| 36 | uint16_t pn_length; /* Big-endian message byte length (minus 6) */ |
| 37 | uint8_t pn_robj; /* Receiver object ID */ |
| 38 | uint8_t pn_sobj; /* Sender object ID */ |
| 39 | }; |
| 40 | |
Rémi Denis-Courmont | ac2dc8c | 2008-09-30 02:52:01 -0700 | [diff] [blame] | 41 | On Linux, the link-layer header includes the pn_media byte (see below). |
| 42 | The next 7 bytes are part of the network-layer header. |
| 43 | |
Matt LaPlante | 19f5946 | 2009-04-27 15:06:31 +0200 | [diff] [blame] | 44 | The device ID is split: the 6 higher-order bits constitute the device |
Rémi Denis-Courmont | ac2dc8c | 2008-09-30 02:52:01 -0700 | [diff] [blame] | 45 | address, while the 2 lower-order bits are used for multiplexing, as are |
| 46 | the 8-bit object identifiers. As such, Phonet can be considered as a |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 47 | network layer with 6 bits of address space and 10 bits for transport |
| 48 | protocol (much like port numbers in IP world). |
| 49 | |
Rémi Denis-Courmont | ac2dc8c | 2008-09-30 02:52:01 -0700 | [diff] [blame] | 50 | The modem always has address number zero. All other device have a their |
| 51 | own 6-bit address. |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 52 | |
| 53 | |
| 54 | Link layer |
| 55 | ---------- |
| 56 | |
| 57 | Phonet links are always point-to-point links. The link layer header |
| 58 | consists of a single Phonet media type byte. It uniquely identifies the |
| 59 | link through which the packet is transmitted, from the modem's |
Rémi Denis-Courmont | ac2dc8c | 2008-09-30 02:52:01 -0700 | [diff] [blame] | 60 | perspective. Each Phonet network device shall prepend and set the media |
| 61 | type byte as appropriate. For convenience, a common phonet_header_ops |
| 62 | link-layer header operations structure is provided. It sets the |
| 63 | media type according to the network device hardware address. |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 64 | |
Rémi Denis-Courmont | ac2dc8c | 2008-09-30 02:52:01 -0700 | [diff] [blame] | 65 | Linux Phonet network interfaces support a dedicated link layer packets |
| 66 | type (ETH_P_PHONET) which is out of the Ethernet type range. They can |
| 67 | only send and receive Phonet packets. |
| 68 | |
| 69 | The virtual TUN tunnel device driver can also be used for Phonet. This |
| 70 | requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case, |
| 71 | there is no link-layer header, so there is no Phonet media type byte. |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 72 | |
| 73 | Note that Phonet interfaces are not allowed to re-order packets, so |
| 74 | only the (default) Linux FIFO qdisc should be used with them. |
| 75 | |
| 76 | |
| 77 | Network layer |
| 78 | ------------- |
| 79 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 80 | The Phonet socket address family maps the Phonet packet header:: |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 81 | |
| 82 | struct sockaddr_pn { |
| 83 | sa_family_t spn_family; /* AF_PHONET */ |
| 84 | uint8_t spn_obj; /* Object ID */ |
| 85 | uint8_t spn_dev; /* Device ID */ |
| 86 | uint8_t spn_resource; /* Resource or function */ |
| 87 | uint8_t spn_zero[...]; /* Padding */ |
| 88 | }; |
| 89 | |
| 90 | The resource field is only used when sending and receiving; |
| 91 | It is ignored by bind() and getsockname(). |
| 92 | |
| 93 | |
| 94 | Low-level datagram protocol |
| 95 | --------------------------- |
| 96 | |
| 97 | Applications can send Phonet messages using the Phonet datagram socket |
| 98 | protocol from the PF_PHONET family. Each socket is bound to one of the |
| 99 | 2^10 object IDs available, and can send and receive packets with any |
| 100 | other peer. |
| 101 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 102 | :: |
| 103 | |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 104 | struct sockaddr_pn addr = { .spn_family = AF_PHONET, }; |
| 105 | ssize_t len; |
| 106 | socklen_t addrlen = sizeof(addr); |
| 107 | int fd; |
| 108 | |
| 109 | fd = socket(PF_PHONET, SOCK_DGRAM, 0); |
| 110 | bind(fd, (struct sockaddr *)&addr, sizeof(addr)); |
| 111 | /* ... */ |
| 112 | |
| 113 | sendto(fd, msg, msglen, 0, (struct sockaddr *)&addr, sizeof(addr)); |
| 114 | len = recvfrom(fd, buf, sizeof(buf), 0, |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 115 | (struct sockaddr *)&addr, &addrlen); |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 116 | |
| 117 | This protocol follows the SOCK_DGRAM connection-less semantics. |
| 118 | However, connect() and getpeername() are not supported, as they did |
| 119 | not seem useful with Phonet usages (could be added easily). |
| 120 | |
| 121 | |
Rémi Denis-Courmont | 274a517 | 2010-09-15 12:30:15 +0000 | [diff] [blame] | 122 | Resource subscription |
| 123 | --------------------- |
| 124 | |
| 125 | A Phonet datagram socket can be subscribed to any number of 8-bits |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 126 | Phonet resources, as follow:: |
Rémi Denis-Courmont | 274a517 | 2010-09-15 12:30:15 +0000 | [diff] [blame] | 127 | |
| 128 | uint32_t res = 0xXX; |
| 129 | ioctl(fd, SIOCPNADDRESOURCE, &res); |
| 130 | |
| 131 | Subscription is similarly cancelled using the SIOCPNDELRESOURCE I/O |
| 132 | control request, or when the socket is closed. |
| 133 | |
| 134 | Note that no more than one socket can be subcribed to any given |
| 135 | resource at a time. If not, ioctl() will return EBUSY. |
| 136 | |
| 137 | |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 138 | Phonet Pipe protocol |
| 139 | -------------------- |
| 140 | |
| 141 | The Phonet Pipe protocol is a simple sequenced packets protocol |
| 142 | with end-to-end congestion control. It uses the passive listening |
| 143 | socket paradigm. The listening socket is bound to an unique free object |
| 144 | ID. Each listening socket can handle up to 255 simultaneous |
| 145 | connections, one per accept()'d socket. |
| 146 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 147 | :: |
| 148 | |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 149 | int lfd, cfd; |
| 150 | |
| 151 | lfd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE); |
| 152 | listen (lfd, INT_MAX); |
| 153 | |
| 154 | /* ... */ |
| 155 | cfd = accept(lfd, NULL, NULL); |
| 156 | for (;;) |
| 157 | { |
| 158 | char buf[...]; |
| 159 | ssize_t len = read(cfd, buf, sizeof(buf)); |
| 160 | |
| 161 | /* ... */ |
| 162 | |
| 163 | write(cfd, msg, msglen); |
| 164 | } |
| 165 | |
Rémi Denis-Courmont | 297edb6 | 2011-03-08 22:44:12 +0000 | [diff] [blame] | 166 | Connections are traditionally established between two endpoints by a |
| 167 | "third party" application. This means that both endpoints are passive. |
| 168 | |
| 169 | |
| 170 | As of Linux kernel version 2.6.39, it is also possible to connect |
| 171 | two endpoints directly, using connect() on the active side. This is |
| 172 | intended to support the newer Nokia Wireless Modem API, as found in |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 173 | e.g. the Nokia Slim Modem in the ST-Ericsson U8500 platform:: |
Rémi Denis-Courmont | 297edb6 | 2011-03-08 22:44:12 +0000 | [diff] [blame] | 174 | |
| 175 | struct sockaddr_spn spn; |
| 176 | int fd; |
| 177 | |
| 178 | fd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE); |
| 179 | memset(&spn, 0, sizeof(spn)); |
| 180 | spn.spn_family = AF_PHONET; |
| 181 | spn.spn_obj = ...; |
| 182 | spn.spn_dev = ...; |
| 183 | spn.spn_resource = 0xD9; |
| 184 | connect(fd, (struct sockaddr *)&spn, sizeof(spn)); |
| 185 | /* normal I/O here ... */ |
| 186 | close(fd); |
| 187 | |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 188 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 189 | .. Warning: |
| 190 | |
| 191 | When polling a connected pipe socket for writability, there is an |
| 192 | intrinsic race condition whereby writability might be lost between the |
| 193 | polling and the writing system calls. In this case, the socket will |
| 194 | block until write becomes possible again, unless non-blocking mode |
| 195 | is enabled. |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 196 | |
| 197 | |
| 198 | The pipe protocol provides two socket options at the SOL_PNPIPE level: |
| 199 | |
| 200 | PNPIPE_ENCAP accepts one integer value (int) of: |
| 201 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 202 | PNPIPE_ENCAP_NONE: |
| 203 | The socket operates normally (default). |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 204 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 205 | PNPIPE_ENCAP_IP: |
| 206 | The socket is used as a backend for a virtual IP |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 207 | interface. This requires CAP_NET_ADMIN capability. GPRS data |
| 208 | support on Nokia modems can use this. Note that the socket cannot |
| 209 | be reliably poll()'d or read() from while in this mode. |
| 210 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 211 | PNPIPE_IFINDEX |
| 212 | is a read-only integer value. It contains the |
| 213 | interface index of the network interface created by PNPIPE_ENCAP, |
| 214 | or zero if encapsulation is off. |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 215 | |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 216 | PNPIPE_HANDLE |
| 217 | is a read-only integer value. It contains the underlying |
| 218 | identifier ("pipe handle") of the pipe. This is only defined for |
| 219 | socket descriptors that are already connected or being connected. |
Rémi Denis-Courmont | acaf7df | 2011-03-08 22:44:11 +0000 | [diff] [blame] | 220 | |
Rémi Denis-Courmont | 95430c0 | 2008-10-05 11:16:36 -0700 | [diff] [blame] | 221 | |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 222 | Authors |
| 223 | ------- |
| 224 | |
| 225 | Linux Phonet was initially written by Sakari Ailus. |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 226 | |
Remi Denis-Courmont | 953f551 | 2008-09-22 20:09:46 -0700 | [diff] [blame] | 227 | Other contributors include Mikä Liljeberg, Andras Domokos, |
| 228 | Carlos Chinea and Rémi Denis-Courmont. |
Mauro Carvalho Chehab | 6e94eaa | 2020-04-30 18:04:12 +0200 | [diff] [blame] | 229 | |
| 230 | Copyright |copy| 2008 Nokia Corporation. |