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