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