|
| 1 | +Linux Phonet protocol family |
| 2 | +============================ |
| 3 | + |
| 4 | +Introduction |
| 5 | +------------ |
| 6 | + |
| 7 | +Phonet is a packet protocol used by Nokia cellular modems for both IPC |
| 8 | +and RPC. With the Linux Phonet socket family, Linux host processes can |
| 9 | +receive and send messages from/to the modem, or any other external |
| 10 | +device attached to the modem. The modem takes care of routing. |
| 11 | + |
| 12 | +Phonet packets can be exchanged through various hardware connections |
| 13 | +depending on the device, such as: |
| 14 | + - USB with the CDC Phonet interface, |
| 15 | + - infrared, |
| 16 | + - Bluetooth, |
| 17 | + - an RS232 serial port (with a dedicated "FBUS" line discipline), |
| 18 | + - the SSI bus with some TI OMAP processors. |
| 19 | + |
| 20 | + |
| 21 | +Packets format |
| 22 | +-------------- |
| 23 | + |
| 24 | +Phonet packets have a common header as follows: |
| 25 | + |
| 26 | + struct phonethdr { |
| 27 | + uint8_t pn_media; /* Media type (link-layer identifier) */ |
| 28 | + uint8_t pn_rdev; /* Receiver device ID */ |
| 29 | + uint8_t pn_sdev; /* Sender device ID */ |
| 30 | + uint8_t pn_res; /* Resource ID or function */ |
| 31 | + uint16_t pn_length; /* Big-endian message byte length (minus 6) */ |
| 32 | + uint8_t pn_robj; /* Receiver object ID */ |
| 33 | + uint8_t pn_sobj; /* Sender object ID */ |
| 34 | + }; |
| 35 | + |
| 36 | +On Linux, the link-layer header includes the pn_media byte (see below). |
| 37 | +The next 7 bytes are part of the network-layer header. |
| 38 | + |
| 39 | +The device ID is split: the 6 higher-order bits consitute the device |
| 40 | +address, while the 2 lower-order bits are used for multiplexing, as are |
| 41 | +the 8-bit object identifiers. As such, Phonet can be considered as a |
| 42 | +network layer with 6 bits of address space and 10 bits for transport |
| 43 | +protocol (much like port numbers in IP world). |
| 44 | + |
| 45 | +The modem always has address number zero. All other device have a their |
| 46 | +own 6-bit address. |
| 47 | + |
| 48 | + |
| 49 | +Link layer |
| 50 | +---------- |
| 51 | + |
| 52 | +Phonet links are always point-to-point links. The link layer header |
| 53 | +consists of a single Phonet media type byte. It uniquely identifies the |
| 54 | +link through which the packet is transmitted, from the modem's |
| 55 | +perspective. Each Phonet network device shall prepend and set the media |
| 56 | +type byte as appropriate. For convenience, a common phonet_header_ops |
| 57 | +link-layer header operations structure is provided. It sets the |
| 58 | +media type according to the network device hardware address. |
| 59 | + |
| 60 | +Linux Phonet network interfaces support a dedicated link layer packets |
| 61 | +type (ETH_P_PHONET) which is out of the Ethernet type range. They can |
| 62 | +only send and receive Phonet packets. |
| 63 | + |
| 64 | +The virtual TUN tunnel device driver can also be used for Phonet. This |
| 65 | +requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case, |
| 66 | +there is no link-layer header, so there is no Phonet media type byte. |
| 67 | + |
| 68 | +Note that Phonet interfaces are not allowed to re-order packets, so |
| 69 | +only the (default) Linux FIFO qdisc should be used with them. |
| 70 | + |
| 71 | + |
| 72 | +Network layer |
| 73 | +------------- |
| 74 | + |
| 75 | +The Phonet socket address family maps the Phonet packet header: |
| 76 | + |
| 77 | + struct sockaddr_pn { |
| 78 | + sa_family_t spn_family; /* AF_PHONET */ |
| 79 | + uint8_t spn_obj; /* Object ID */ |
| 80 | + uint8_t spn_dev; /* Device ID */ |
| 81 | + uint8_t spn_resource; /* Resource or function */ |
| 82 | + uint8_t spn_zero[...]; /* Padding */ |
| 83 | + }; |
| 84 | + |
| 85 | +The resource field is only used when sending and receiving; |
| 86 | +It is ignored by bind() and getsockname(). |
| 87 | + |
| 88 | + |
| 89 | +Low-level datagram protocol |
| 90 | +--------------------------- |
| 91 | + |
| 92 | +Applications can send Phonet messages using the Phonet datagram socket |
| 93 | +protocol from the PF_PHONET family. Each socket is bound to one of the |
| 94 | +2^10 object IDs available, and can send and receive packets with any |
| 95 | +other peer. |
| 96 | + |
| 97 | + struct sockaddr_pn addr = { .spn_family = AF_PHONET, }; |
| 98 | + ssize_t len; |
| 99 | + socklen_t addrlen = sizeof(addr); |
| 100 | + int fd; |
| 101 | + |
| 102 | + fd = socket(PF_PHONET, SOCK_DGRAM, 0); |
| 103 | + bind(fd, (struct sockaddr *)&addr, sizeof(addr)); |
| 104 | + /* ... */ |
| 105 | + |
| 106 | + sendto(fd, msg, msglen, 0, (struct sockaddr *)&addr, sizeof(addr)); |
| 107 | + len = recvfrom(fd, buf, sizeof(buf), 0, |
| 108 | + (struct sockaddr *)&addr, &addrlen); |
| 109 | + |
| 110 | +This protocol follows the SOCK_DGRAM connection-less semantics. |
| 111 | +However, connect() and getpeername() are not supported, as they did |
| 112 | +not seem useful with Phonet usages (could be added easily). |
| 113 | + |
| 114 | + |
| 115 | +Phonet Pipe protocol |
| 116 | +-------------------- |
| 117 | + |
| 118 | +The Phonet Pipe protocol is a simple sequenced packets protocol |
| 119 | +with end-to-end congestion control. It uses the passive listening |
| 120 | +socket paradigm. The listening socket is bound to an unique free object |
| 121 | +ID. Each listening socket can handle up to 255 simultaneous |
| 122 | +connections, one per accept()'d socket. |
| 123 | + |
| 124 | + int lfd, cfd; |
| 125 | + |
| 126 | + lfd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE); |
| 127 | + listen (lfd, INT_MAX); |
| 128 | + |
| 129 | + /* ... */ |
| 130 | + cfd = accept(lfd, NULL, NULL); |
| 131 | + for (;;) |
| 132 | + { |
| 133 | + char buf[...]; |
| 134 | + ssize_t len = read(cfd, buf, sizeof(buf)); |
| 135 | + |
| 136 | + /* ... */ |
| 137 | + |
| 138 | + write(cfd, msg, msglen); |
| 139 | + } |
| 140 | + |
| 141 | +Connections are established between two endpoints by a "third party" |
| 142 | +application. This means that both endpoints are passive; so connect() |
| 143 | +is not possible. |
| 144 | + |
| 145 | +WARNING: |
| 146 | +When polling a connected pipe socket for writability, there is an |
| 147 | +intrinsic race condition whereby writability might be lost between the |
| 148 | +polling and the writing system calls. In this case, the socket will |
| 149 | +block until write because possible again, unless non-blocking mode |
| 150 | +becomes enabled. |
| 151 | + |
| 152 | + |
| 153 | +The pipe protocol provides two socket options at the SOL_PNPIPE level: |
| 154 | + |
| 155 | + PNPIPE_ENCAP accepts one integer value (int) of: |
| 156 | + |
| 157 | + PNPIPE_ENCAP_NONE: The socket operates normally (default). |
| 158 | + |
| 159 | + PNPIPE_ENCAP_IP: The socket is used as a backend for a virtual IP |
| 160 | + interface. This requires CAP_NET_ADMIN capability. GPRS data |
| 161 | + support on Nokia modems can use this. Note that the socket cannot |
| 162 | + be reliably poll()'d or read() from while in this mode. |
| 163 | + |
| 164 | + PNPIPE_IFINDEX is a read-only integer value. It contains the |
| 165 | + interface index of the network interface created by PNPIPE_ENCAP, |
| 166 | + or zero if encapsulation is off. |
| 167 | + |
| 168 | + |
| 169 | +Authors |
| 170 | +------- |
| 171 | + |
| 172 | +Linux Phonet was initially written by Sakari Ailus. |
| 173 | +Other contributors include Mikä Liljeberg, Andras Domokos, |
| 174 | +Carlos Chinea and Rémi Denis-Courmont. |
| 175 | +Copyright (C) 2008 Nokia Corporation. |
0 commit comments