Commit | Line | Data |
---|---|---|
6e94eaaa MCC |
1 | .. SPDX-License-Identifier: GPL-2.0 |
2 | .. include:: <isonum.txt> | |
3 | ||
4 | ============================ | |
953f5517 RDC |
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: | |
6e94eaaa | 18 | |
953f5517 RDC |
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 | ||
6e94eaaa | 29 | Phonet packets have a common header as follows:: |
953f5517 RDC |
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 | ||
ac2dc8ca RDC |
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 | ||
19f59460 | 44 | The device ID is split: the 6 higher-order bits constitute the device |
ac2dc8ca RDC |
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 | |
953f5517 RDC |
47 | network layer with 6 bits of address space and 10 bits for transport |
48 | protocol (much like port numbers in IP world). | |
49 | ||
ac2dc8ca RDC |
50 | The modem always has address number zero. All other device have a their |
51 | own 6-bit address. | |
953f5517 RDC |
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 | |
ac2dc8ca RDC |
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. | |
64 | ||
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. | |
953f5517 RDC |
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 | ||
6e94eaaa | 80 | The Phonet socket address family maps the Phonet packet header:: |
953f5517 RDC |
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 | ||
6e94eaaa MCC |
102 | :: |
103 | ||
953f5517 RDC |
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, | |
6e94eaaa | 115 | (struct sockaddr *)&addr, &addrlen); |
953f5517 RDC |
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 | ||
274a517e RDC |
122 | Resource subscription |
123 | --------------------- | |
124 | ||
125 | A Phonet datagram socket can be subscribed to any number of 8-bits | |
6e94eaaa | 126 | Phonet resources, as follow:: |
274a517e RDC |
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 | ||
a266ef69 | 134 | Note that no more than one socket can be subscribed to any given |
274a517e RDC |
135 | resource at a time. If not, ioctl() will return EBUSY. |
136 | ||
137 | ||
95430c0b RDC |
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 | ||
6e94eaaa MCC |
147 | :: |
148 | ||
95430c0b RDC |
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 | ||
297edb60 RDC |
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 | |
6e94eaaa | 173 | e.g. the Nokia Slim Modem in the ST-Ericsson U8500 platform:: |
297edb60 RDC |
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 | ||
95430c0b | 188 | |
6e94eaaa MCC |
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. | |
95430c0b RDC |
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 | ||
6e94eaaa MCC |
202 | PNPIPE_ENCAP_NONE: |
203 | The socket operates normally (default). | |
95430c0b | 204 | |
6e94eaaa MCC |
205 | PNPIPE_ENCAP_IP: |
206 | The socket is used as a backend for a virtual IP | |
95430c0b RDC |
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 | ||
6e94eaaa MCC |
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. | |
95430c0b | 215 | |
6e94eaaa MCC |
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. | |
acaf7df6 | 220 | |
95430c0b | 221 | |
953f5517 RDC |
222 | Authors |
223 | ------- | |
224 | ||
225 | Linux Phonet was initially written by Sakari Ailus. | |
6e94eaaa | 226 | |
953f5517 RDC |
227 | Other contributors include Mikä Liljeberg, Andras Domokos, |
228 | Carlos Chinea and Rémi Denis-Courmont. | |
6e94eaaa MCC |
229 | |
230 | Copyright |copy| 2008 Nokia Corporation. |