Affix - Technical Documentation: Affix - Open Source Bluetooth Protocol Stack for Linux | ||
---|---|---|
Prev | Chapter 3. Application Programming Interface | Next |
Personal Area Network consist of one GN (Group Network) or NAP (Network access Point) and 1 to 7 PANUs (Personal Area Network User). These form a piconet that uses Bluetooth for communicating between hosts. GN or NAP performs network bridge functions using Bluetooth Network Encapsulation Protocol (BNEP) to transfer Ethernet packets over Bluetooth connection.
To participate in piconet a host's Bluetooth device has to be initialized. During the initialization the host's role is set. After the initialization is completed the host can connect to another host or wait others to connect to it. Usually PANUs connect to GNs or NAPs.
Ethernet packets are transmitted as a single L2CAP packet. They are transmitted in the payload using BNEP. According to PAN profile specification payload can be encrypted (profile secrecy mode 2), but Affix does not support this yet.
Creating a PAN connection with Affix is very straightforward and the API is simple. See the example below.
Table 3-21. Personal area network API
Function | Purpose |
---|---|
int affix_pan_init(char *name, int mode); | Initialize the given Bluetooth device for PAN connection. Mode is one of AFFIX_PAN_PANU, AFFIX_PAN_NAP, AFFIX_NAP_GN, AFFIX_PAN_AUTO. |
int affix_pan_connect(struct sockaddr_affix *sa, int role); | Connect to a remote host. PAN have to be initialized before calling this. Role parameter defines peer's role. It is one of the following: AFFIX_PAN_NAP, AFFIX_NAP_GN. This function is also used to disconnecting the device. When disconnecting set remote address to BDADDR_ANY. |
The following simple example illustrates creating and closing a PAN connection.
char btdev[IFNAMSIZ] = "bt0"; char remote_host[] = "00:0c:76:b1:03:2d"; int err, role = AFFIX_PAN_NAP; BD_ADDR bda; struct sockaddr_affix saddr; /* Initialize this host as an user */ err = affix_pan_init(btdev, AFFIX_PAN_PANU); if (err) { BTERROR("Error while initalizing PAN\n"); fprintf(stderr, "%s\n", hci_error(err)); exit(1); } /* PAN initialized. Now, try connecting */ /* Parse the string presentation of the address */ err = btdev_get_bda(&bda, remote_host); if (err) { fprintf(stderr, "Incorrect address\n"); return 1; } saddr.family = PF_AFFIX; saddr.bda = bda; saddr.devnum = hci_devnum(btdev); err = affix_pan_connect(&saddr, role); if (err) { if (errno == EINVAL) fprintf(stderr, "This role is not valid.\n"); else fprintf(stderr, "Creating connection failed!\n"); exit(1); } else fprintf(stderr, "Connection established. \n"); /* Now the connections is established. In this example we are going to close it now*/ saddr.bda = BDADDR_ANY; /* BDADDR_ANY means disconnect */ err = affix_pan_connect(&saddr, 0); if (err) { fprintf(stderr, "Closing the connection failed\n"); exit(1); } else fprintf(stderr, "Connection closed.\n");
As piconets bandwidth is limited it is often good idea to filter out some unnecessary traffic. Affix implements this filtering to reduce wasted bandwidth. For example video transmission and IPv6 packets may be dropped at NAP.
Look at http://www.iana.org/assignments/ethernet-numbers for protocol types. Multicast addresses for IPv4 are listed at http://www.iana.org/assignments/multicast-addresses. For IPv6 see http://www.iana.org/assignments/ipv6-multicast-addresses and http://www.rfc-archive.org/getrfc.php?rfc=2373.
You need to fill specific data structures when setting filters. Both protocol and multicasting filters has their own structures. Multicast filter structure is defined as follows.
typedef struct { __u16 count; /* number of filter entrys, 0 = no filter */ ETH_ADDR multicast[MULTICAST_FILTER_MAX][2] /* start_range - stop_range pairs in network byte order */ } multicast_filter;
Protocol filter definition is:
typedef struct { __u16 count; /* number of filter entrys, 0 = no filter */ __u16 protocol[PROTOCOL_FILTER_MAX][2]; /* start_range - stop_range pairs in network byte order */ } protocol_filter;
Maximum amount of filter ranges are defined with MULTICAST_FILTER_MAX and PROTOCOL_FILTER_MAX.
You should use ioctl() function call to set filters. The function call interface is
ioctl(file_descriptor, type, value);
First you have to open a socket to set or get the filter values. The type parameter defines the type of setting that is set or got. See the table below for filter settings. The value is a pointer to ifreq struct. When setting a filter it holds the filter information. When getting the filter information the structure pointed by this is filled.
Table 3-22. Filter types for ioctl() function
Define | Purpose |
---|---|
SIOCSFILTERPROTOCOL | Set protocol filter |
SIOCSFILTERMULTICAST | Set multicast filter |
SIOCGFILTERPROTOCOL | Get protocol filter |
SIOCGFILTERMULTICAST | Get multicast filter |
Follows example of setting protocol filter.
struct ifreq ifr; protocol_filter pf; int fd; char interface[] = "bt0"; /* Create socket */ fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (fd < 0) { fprintf(stderr, "error opening socket"); return -1; } memset(&pf, 0, sizeof(pf)); strncpy(ifr.ifr_name, interface, IFNAMSIZ); /* Set filter information. Allow only IPv4 traffic. */ pf.count = 1; pf.protocol[0][F_START] = 0x800; pf.protocol[0][F_STOP] = 0x800; /* Set the filter */ ifr.ifr_ifru.ifru_data = (char*) &pf; if ((result = ioctl(fd, SIOCSFILTERPROTOCOL, &ifr))) { fprintf(stderr, "ioctl error when setting protocol filter "); }