Unison Help
- Unison Kernel
- Pthreads
- pthread_create()
- pthread_exit()
- pthread_self()
- pthread_equal()
- pthread_join()
- pthread_detach()
- pthread_setschedparam()
- pthread_getschedparam()
- pthread_attr_init()
- pthread_attr_destroy()
- pthread_attr_setstackaddr()
- pthread_attr_getstackaddr()
- pthread_attr_setstacksize()
- pthread_attr_getstacksize()
- pthread_attr_setschedparam()
- pthread_attr_getschedparam()
- pthread_attr_setdetachstate()
- pthread_attr_getdetachstate()
- pthread_stackinfo()
- pthread_setprio()
- pthread_getprio()
- sched_get_priority_max()
- sched_get_priority_min()
- sched_yield()
- Pthread Cancellation
- Mutex
- Semaphores
- Message Queues
- Conditional Variables
- Barriers
- Timers
- Clocks
- Memory Allocation
- Rendezvous
- Interrupts
- Directory Services
- Miscellaneous
- Pthreads
- Unison I/O Library
- Unison STDIO Library
- STDIO Library Calls
- clearerr()
- dprintf()
- fclose()
- fdopen()
- feof()
- ferror()
- fileno()
- fflush()
- fgetc()
- fgetpos()
- fgets()
- fopen()
- fprintf()
- fputc()
- fputs()
- fread()
- freopen()
- fscanf()
- fseek()
- fseeko()
- fsetpos()
- ftell()
- ftello()
- fwrite()
- getc()
- getc_unlocked()
- getchar()
- getchar_unlocked()
- getdelim()
- getline()
- gets()
- get_stderr_ptr()
- get_stdin_ptr()
- get_stdout_ptr()
- noperprintf()
- perprintf()
- perror()
- posix_compat()
- printf()
- putc()
- putc_unlocked()
- putchar()
- putchar_unlocked()
- puts()
- remove()
- rewind()
- scanf()
- setbuf()
- setvbuf()
- snprintf()
- sprintf()
- sscanf()
- stderr_init()
- stderr_close()
- stdin_init()
- stdin_close()
- stdout_init()
- stdout_close()
- vdprintf()
- vscanf()
- vsscanf()
- vfscanf()
- vprintf()
- vsnprintf()
- vsprintf()
- vfprintf()
- ungetc()
- Do-nothing Stubs
- STDIO Library Calls
- Unison LIBC Library
- Unison I/O Servers
- Graphics, Camera, Video, Audio
- Network Protocols
- TCP and UDP Server - tcpd
- DHCP Client Service - dhcp client
- DHCP Server - dhcpd
- Telnet Server - telnetd
- Tiny FTP Server - tftpd
- Point to Point - pppd
- Network Translation - NAT with PAT
- Firewall
- Tiny HTTP Server - thttpd
- Tiny HTTP Server with TLS
- POP3 Server
- Simple Mail Transfer Protocol Services (SMTP)
- Bootp Protocol
- File Transfer Protocol Server (FTP)
- File Transfer Client Services
- RPC / XDR
- DNS Client
- HTTP/HTTPS Client
- REST Client
- AutoIP Service - autoip client
- mDNS server - mdnsd
- SNTP Client
- SNMP Agent - Snmpd server
- SSL/TLS library
- SSH server
- IP security
- Power Control
- Serial I/O
- System Services
- Universal Serial Bus (USB)
- Wireless
- Remedy Tools for Unison
7.31.5.BlueTooth Server #
NAME
Bluetooth Server (btd)
SYNOPSIS
#include <sys.h>
#include <fcntl.h>
#include <iorqst.h>
#include <stdio.h>
#include <bluetooth.h>
int _bt_server(char* bt_setup, char hw_port_num, char hw_type, void * callback);
DESCRIPTION
The btd is a small and fast Bluetooth server. The Bluetooth protocol stack is flexible and can be easily extending to support new protocols and profiles.
The current version supports the following protocols:
Host Controller Interface (HCI)
Logical Link Control and Adaptation Protocol ( L2CAP)
Service Discovery Protocol (SDP)
RFCOMM
Supported profiles
Generic Access Profile (GAP)
Serial Port Profile (SPP)
Hands Free Profile (HFP)
Headset Profile (HSP)
The btd is instantiated with the command:
_bt_server((char*)&bt_setup, portnum, dev_type, user_callback );
After Bluetooth server has started it can be accessed using standard POSIX open/close/ioctl commands.
To access to BT server user must register it in local directory database:
dir_register(“/dev/bt/root”, pid, TYPE_SERVER);
The default bluetooth server path is: “/dev/bt/root”
. Default path to Bluetooth profiles is “/dev/bt”.
Example
bt0_fd = open("/dev/bt/root", O_RDWR, 0);
The _bt_server required parameters:
- bt_setup – parameters for initialization of the hardware bluetooth interface. bt_setup has callback function named read_init_file. This function used by BT stack to load init file to BT chip. If initialisation is not needed – write NULL to read_init_file.
int (*read_init_file)(char *data, int size, int * pos, void * arg); data - pointer to read data buffer size - size requested to be read pos - current position in read file arg - addition command depending of chip driver (for example "-o" for open or "-r" for read initialization file)
- portnum – port selection for the bluetooth module.
- dev_type – selection of the hardware transport for current module. The current version supports a UART (ebt_hw_uart) and SPI (ebt_hw_spi) transport. For other versions contact the factory.
- user_callback – User callback function for handling events from the Bluetooth server.
prototype of user_callback function:
int user_callback(tbt_evt * evt, int * resp, int evt_type);
parameters:
- * evt – struct which holds data for the user (depends on the evt_type)
- * resp – depending on the evt_type, the user must change this information to send response data.
- evt_type – type of event.
List of available event types:
1. BT_CONNECT_REQ – request connect from remote peer
evt->con_evt.name – name of remote peer (e.g. “BTPC_1”)
evt->con_evt.bdaddr – BDADDR of remote peer (e.g. 123456)
evt->con_evt.svc_name – connecting service name (“SPP” for “SPP1” )
evt->con_evt.svc_port – connecting service port ( (1) for “SPP1” )
user response:
*resp = (-1) – reject connection
*resp = (1) – accept connection
Example:
——————————————————-
xprintf("Connect request from \"%s\", bdaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",evt->con_evt.name, evt->con_evt.bdaddr->addr[5], evt->con_evt.bdaddr->addr[4], evt->con_evt.bdaddr->addr[3], evt->con_evt.bdaddr->addr[2], evt->con_evt.bdaddr->addr[1], evt->con_evt.bdaddr->addr[0]); xprintf("Service %s%d\n",evt->con_evt.svc_name, evt->con_evt.svc_port); *resp = 1; //accepting connect request. Send -1 to reject connect request
——————————————————-
2. BT_CONNECT_EVT – request event. Sent when connection established
evt->con_evt.name – name of remote peer (e.g. “BTPC_1”)
evt->con_evt.bdaddr – BDADDR of remote peer (e.g. 123456)
evt->con_evt.svc_name – connecting service name ( “SPP” for “SPP1”)
evt->con_evt.svc_port – connecting service port ( (1) for “SPP1”)
user response: NONE
3. BT_DISCONNECT_EVT – request event. Sent when connction broken
evt->discon_evt.name – name of remote peer (e.g. “BTPC_1”)
evt->discon_evt.bdaddr – BDADDR of remote peer (e.g. 123456)
evt->discon_evt.svc_name – connecting service name (“SPP” for “SPP1”)
evt->discon_evt.svc_port – connecting service port ( (1) for “SPP1”)
user response: NONE
4. BT_CONNECT_ERR – error establishing a connection.
evt->con_err.name – name of remote peer (e.g. “BTPC_1”)
evt->con_err.bdaddr – BDADDR of remote peer (e.g. 123456)
evt->con_err.svc_name – connecting service name (e.g. “SPP”)
5. BT_PIN_REQ – remote peer requested pin
evt->pin_req.name – name of remote peer (e.g. “0000”). Max 4 symbols
evt->pin_req.bdaddr – BDADDR of remote peer (e.g. 123456)
user response
*resp = -1 – reject pin request
*resp = “XXXX” – send pin (“XXXX”)
Example:
——————————————————-
xprintf("Pin request event \"%s\", BDADDR %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n\n",evt->pin_req.name, evt->pin_req.bdaddr->addr[5], evt->pin_req.bdaddr->addr[4], evt->pin_req.bdaddr->addr[3], evt->pin_req.bdaddr->addr[2], evt->pin_req.bdaddr->addr[1], evt->pin_req.bdaddr->addr[0]); memcpy((char *)evt->pin_req.pin, "0000", 5);
——————————————————-
6. BT_KEY_NOT – Link Key Notification event
The Link Key Notification event is used to indicate that a new Link Key has been created for the connection with the device specified in evt->key_evt.bdaddr
evt->key_evt.bdaddr – Remote device BDADDR
evt->key_req.key – Created link key
The Host can save this new Link Key in its own storage for future use
Example:
——————————————————-
xprintf("Key notification event \"%s\", BDADDR %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",evt->key_evt.name, evt->key_evt.bdaddr->addr[5], evt->key_evt.bdaddr->addr[4], evt->key_evt.bdaddr->addr[3], evt->key_evt.bdaddr->addr[2], evt->key_evt.bdaddr->addr[1], evt->key_evt.bdaddr->addr[0]); memcpy(key, evt->key_evt.key, 16); key_set = 1; *resp = 0; //send 1 if you want to store link key to local BT chip database (stored key count is limited)
——————————————————-
7. BT_KEY_REQ – The Link Key Request event is used to indicate that a Link Key is required for
the connection with the device specified in evt->key_req.bdaddr.
If key exists – return *resp = 0 and key, in evt->key_req.key, else return *resp = -1
Example:
------------------------------------------------------- if (key_set == 1) { memcpy(evt->key_req.key, key, 16); *resp = 0; }else *resp = -1; -------------------------------------------------------
8. BT_KEY_DELETE – Request to delete existing link key (received from already paired device) from database
evt->key_delete_evt.name – paired device name
evt->key_delete_evt.bdaddr – paired device BDADDR
9. BT_INQ_COMPLEATE – indicates that the Inquiry is finished. Return status Inquiry process.
evt->inq_evt.devnum – status of Inquiry process. Return founded devices number or (-1) if the process failed.
All communication with Bluetooth server takes with open/close/ioctl functions.
To start the BT module, the user must call the open function:
bt0_fd = open("/dev/bt/root", O_RDWR, 0);
Now the user can use ioctl(bt0_fd) command to communicate with the bluetooth server.
ioctl(fd, CMD, cmd_param);
where:
- fd – opened BT device file descriptor
- CMD – command class (BTIOCTL)
- cmd_param – pointer to the command parameters;
Example:
//========================================================int bt_fd; BT_IO_CMD bt_cmd; if((bt0_fd = open("/dev/bt/root", O_RDWR, 0)) == -1) { xprintf("Can't open bluetooth hardware\n"); //opening BT device descriptor pthread_exit(0); } bt_cmd.cmd = BTSNAME; bt_cmd.io_set_name.name = "Rowebots BT"; xprintf("BT name: %s\n", bt_cmd.io_set_name.name ); //set local name ioctl(bt0_fd, BTIOCTL, &bt_cmd);
//========================================================
// Command list
//========================================================BTSDISC – set discoverable mode
struct BT_STDISCOVER_st { int cmd; //BTSDISC int mode; //discover set (int) //DISCOVER_GENERAL - all devices can see module //DISCOVER_NONE - all devices can't see module };
BTSCOD – set local device COD (ClassOfDevice)
struct BT_SCOD_st { int cmd; //BTSCOD int COD; //set class of device. Valid values for this parameter are specified in the //Bluetooth Assigned Numbers Document www.bluetooth.com. };
BTGLNAME – get local device name
struct BT_GLNAME_st { int cmd; //BTGLNAME char * name; //name };
BTSNAME – set local device name
struct BT_SNAME_st { int cmd; //BTSNAME char * name; //name };
GETLADDR – get local BD addr
struct BT_GETLADDR_st { int cmd; //BDADDR struct bd_addr * bdaddr; //local BD addr };
Example:
bt_cmd.cmd = GETLADDR; ioctl(bt0_fd, BTIOCTL, &bt_cmd); fprintf(tty_file,"New bdaddr: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", bt_cmd.io_get_local_addr.bdaddr->addr[5], bt_cmd.io_get_local_addr.bdaddr->addr[4], bt_cmd.io_get_local_addr.bdaddr->addr[3], bt_cmd.io_get_local_addr.bdaddr->addr[2], bt_cmd.io_get_local_addr.bdaddr->addr[1], bt_cmd.io_get_local_addr.bdaddr->addr[0]);
BTSETLADDR – set local BD addr
struct BT_SETLADDR_st { int cmd; struct bd_addr * bdaddr; };
Example:
bt_cmd.cmd = BTSETLADDR; bt_cmd.io_set_local_addr.bdaddr->addr[0] = 0x11; bt_cmd.io_set_local_addr.bdaddr->addr[1] = 0x22; bt_cmd.io_set_local_addr.bdaddr->addr[2] = 0x33; bt_cmd.io_set_local_addr.bdaddr->addr[3] = 0x44; bt_cmd.io_set_local_addr.bdaddr->addr[4] = 0x55; bt_cmd.io_set_local_addr.bdaddr->addr[5] = 0x66; if (ioctl(bt0_fd, BTIOCTL, &bt_cmd)) fprintf(tty_file,"Error\n"); else fprintf(tty_file,"OK\n");
BTDISCOVER – Performs device discovery
struct BT_DISCOVER_st { int cmd; //BTDISCOVER int timeout; //time for device discovery (typically >= 20 sec) };
BTGPLIST – Get total discovered peers cnt
struct BT_GPLIST_st { int cmd; //BTGPLIST int peer_cnt; //discovered peers count };
BTGPBDADDR – Get peer BD addr
struct BT_GPBDADDR_st { int cmd; //BTGPBDADDR int dev_index; //Device index (dev_index <= peer_cnt) struct bd_addr * bdaddr; //return peer BDADDR };
BTGPNAME – Get peer name
struct BT_GPNAME_st { int cmd; //BTGPNAME int dev_index; //Device index (dev_index <= peer_cnt)< char * name; //return peer name };
BTGADDRNAME – Get peer name bt BDADDR
struct BT_GADDRNAME_st { int cmd; //BTGADDRNAME struct bd_addr * bdaddr; //peer BDADDR char * name; //return peer name };
BTGCOD – Get peer COD (class of device)
struct BT_GCOD_st { int cmd; //BTGCOD int dev_index; //Device index (dev_index <= peer_cnt) int COD; //return peer class of device };
BTSVCDISC – Device service discovery
struct BT_SVCDISC_st { int cmd; //BTSVCDISC int dev_index; //Device index (dev_index <= peer_cnt) };
BTSVCMDISC – Device service discovery by bdaddr
struct BT_SVCMDISC_st { int cmd; //BTSVCMDISC struct bd_addr * bdaddr; //peer BDADDR };
BTNSVCCNT – Get device servise cnt
struct BT_NSVCCNT_st { int cmd; //BTNSVCCNT int dev_index; //Device index (dev_index < peer_cnt) int service_cnt; //Return service count of device };
BTSVCPROP – Get service name and port count
struct BT_SVCPROP_st { int cmd; //BTSVCPROP int dev_index; //Device index (dev_index <= peer_cnt) int service_index; //Service index (service_index < service_cnt) char * name; //Service name ("SPP", "HFP"...) int port_cnt; //Service port count };
BTGETSVCONCNT – Get connected services count
struct BT_GETSVCONCNT_st { int cmd; //BTGETSVCONCNT int dev_index; //Device index (dev_index < peer_cnt) int service_cnt; //Get already connected services count };
BTGETSVCCONPROP – Get service properties
struct BT_GETSVCCONPROP_st { int cmd; //BTGETSVCCONPROP int dev_index; /Device index (dev_index < peer_cnt) int service_index; //Service index (service_index < service_cnt) char * svc_name; //Service name ("SPP", "HFP"...) char svc_fd; //connected service index: (0) for HFP0, (1) for SPP1... char out; //connect direction (1 - OUT, 0 - IN) char svc_ch; //channel on which connection is established. char * name; };
BTCONNECT – Connect to remote peer service
struct BT_CONNECT_st { int cmd; //BTCONNECT int dev_index; //Device index (dev_index < peer_cnt) char *svc_name; //Service name ("SPP", "HFP"...) int svc_port; //Service port };
To connect to the SPP1 service set:
*svc_name = “SPP”;
svc_port = 1;BTDISCON – Disconnect from peer service
struct BT_DISCON_st { int cmd; //BTDISCON char *svc_name; //Service name ("SPP", "HFP"...) int svc_port; //Local connected service port };
BTDEVRM – Remove selected device from list with all connected services
struct BT_DEVRM_st { int cmd; //BTDISCON int dev_index; //Device index (dev_index < peer_cnt) };
BTGHWVER – Get Hardware version
struct BT_GHWVER_st { int cmd; char hci_ver; short hci_rev; char lmp_ver; short lmp_subver; short manufacturer; };
BTSCOROUTING – set SCO routing (PCM or SCO)
struct BT_SCOROUTINGst { int cmd; #define SCO_HCI 0 #define SCO_PCM 1 int routing; };
BTWRVOICESETTINGS – set voice settings (for all connections)
BTRDVOICESETTINGS – get current voice settingsstruct BT_VOICE_SETTINGS_st{ int cmd; char icf; //Input Coding char idf; //Input Data Format char iss; //Input Sample Size char acf; //Air Coding Format char lbp; //Linear_PCM_Bit_Pos };
BTSETPWRMOD– set power safe mode
struct BT_SETPWRMODE_st { int cmd; int mode; //power safe mode type. //One of: BT_PWR_ACTIVE, BT_PWR_SLEEP, BT_PWR_DEEP_SLEEP, BT_PWR_OFF void * param; //additional parameter. Typically timeout for enter to sleep mode in msec };
BTSETSLEEPENA – set sleep enable
struct BT_SETSLEEPENA_st { int cmd; int ena; //activate/deactivate power safe mode };
BTGETPOWERSTATE– get current power state
struct BT_GETPWRSTATE_st { int cmd; int ena; //power safe mode activated/deactivated int state; //actual power safe state (1-active/0-sleep) int mode; //power safe mode type. };
Power mode setting example:
BT_IO_CMD bt_cmd; ..... i = 2000; //timeout in msec to enter sleep mode when no activity on HCI interface /*Setup power mode*/ bt_cmd.cmd = BTSETPWRMODE; bt_cmd.io_set_pwr_mode.mode = BT_PWR_DEEP_SLEEP; //deep sleep power mode. bt_cmd.io_set_pwr_mode.param = &i; ioctl(bt0_fd, BTIOCTL, &bt_cmd); ..... /*Activate power safe mechanism*/ bt_cmd.cmd = BTSETSLEEPENA; bt_cmd.io_sleep_ena.ena = 1; // enable sleep mode (0 - disable) ioctl(bt0_fd, BTIOCTL, &bt_cmd); ..... /*Getting current powersafe state*/ bt_cmd.cmd = BTGETPOWERSTATE; ioctl(bt0_fd, BTIOCTL, &bt_cmd); fprintf(tty_file, "We in power safe mode \"%d\"\n", bt_cmd.io_pwr_state.mode); fprintf(tty_file, " --Power manage %s \n", bt_cmd.io_pwr_state.ena ? "enabled" : "disabled"); fprintf(tty_file, " --BT in %s state\n", bt_cmd.io_pwr_state.state ? "Active" : "Power Safe");
BTSTAT – get stack staticstics
struct BT_STATst { int cmd; uint_32 ACL_pkt_in; uint_32 ACL_data_in; uint_32 ACL_pkt_out; uint_32 ACL_data_out; uint_32 SCO_pkt_in; uint_32 SCO_data_in; uint_32 SCO_pkt_out; uint_32 SCO_data_out; uint_32 EVT_pkt; uint_32 EVT_data; uint_32 CMD_pkt; uint_32 CMD_data; };
After the connection is established (receive by callback function event BT_CONNECT_REQ or BT_CONNECT_EVT) – then user can open the connected service. The name of the service is stored in evt->con_evt.svc_name and evt->con_evt.svc_port which was received in the callback function.fd_spp = open(“/dev/bt/SPP0”, O_RDWR, 0); //open “SPP0” service.
Now the user may use the read or write command to send and receive data:
n = read(fd_spp, &temp_buf , 1); if (n!= -1) write(fd_spp,&temp_buf,n);
/////////////////////////////////////////////////////////////////////////////// ////////////////////////////Bluetooth SPP demo///////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
1. Open demo project “bt_spp_XXXXX” in your demo directory, where XXXXX – is the name of your Bluetooth hardware.
For example: bt_spp_PAN1315 for PAN1315 module.
2. Compile and run demo.
3. After the demo runs you can see the following messages:Main here! Start Unison Bluetooth core ver. 1.3.8 TTY Server version = 2.4.0 SPP server ver 0.97 TTY Server version = 2.4.0 Starting Bluetooth Vendor bdaddr: c0:e4:22:8c:f1:8a Setting new bdaddr...OK New bdaddr: 11:22:33:44:55:66 BT name: Rowebots BT Type 'h' for help
Enter ‘h’ command
h =========help======= Type: "l" for print discovered devices Type: "s" for discovery bluetooth devices Type: "p n" for discovery device service n - device number in device list(l) Type: "c dev svc port" for connect to peer dev - device number in discovery list svc - Service name port remote service port Type: "d svc port" for disconnect from peer svc - service name port connected port
After entering the command ‘s’ the result is displayed, for example:
s Discovery devices. Wait some time... Discovery devices complete. Found 1 devices
Enter ‘l’ command:
l ======================== 0. Dev name: "TEST_BT-PC", bdaddr: 00:15:83:3d:0a:57 found 0 services Connected 0 services ========================
Now – searching for available “SPP” service in remote devices.
To search for a Profile on device which is named “RwBt-PC” enter the commandp 0 Discovery device 0 profiles... profile discovery OK l ======================== 0. Dev name: "TEST_BT-PC", bdaddr: 00:15:83:3d:0a:57 found 1 services services: -SPP has 2 ports Connected 0 services ========================
The device found “TEST_BT-PC” and has 2 “SPP” ports. Try to connect to the port “SPP0”
c 0 SPP Connecting to peer 0 Connect event from "RwBt-PC", bdaddr 00:15:83:3d:0a:57 Service SPP0 connect OK l ======================== 0. Dev name: "TEST_BT-PC", bdaddr: 00:15:83:3d:0a:57 found 1 service services: -SPP has 2 ports Connected 1 service service SPP0 - was connected to Remote port SPP0 ========================
Now we can communicate with the remote device using standard open/close/read/write instructions
Example: fd_spp = open("/dev/bt/SPP0", O_RDWR, 0); n = read(fd_spp, &temp_buf , 8); if (n!= -1) write(fd_spp,&temp_buf,n);
to close the communication channel “SPP0” enter the command
d SPP 0 Disconnecting SPP0 Disconnect event from "TEST_BT-PC", bdaddr 00:15:83:3d:0a:57 Service SPP0< l ======================== 0. Dev name: "TEST_BT-PC", bdaddr: 00:15:83:3d:0a:57 found 1 service services: -SPP has 2 ports Connected 0 services ========================
SEE ALSO