How to compile a BlueZ application for ARM-Linux (IMX6UL)? - c

I want to cross compile an application from my workstation (x86, linux) for an ARM application processor.
still now ,I have finished these as blow:
1, for PC ,Ubuntu 16.04,it supports BlueZ already ,I can use Bluetoothctl\hcitool\hciattach in Ubuntu now.
2, for ARM,Linux 4.1 ,it supports BlueZ too,I can use Bluetoothctl\hcitool\hciattachin ARM CHIP.
my demo code is from
https://people.csail.mit.edu/albert/bluez-intro/c404.html
the function of the code below is to scan Bluetooth device .
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
inquiry_info *ii = NULL;
int max_rsp, num_rsp;
int dev_id, sock, len, flags;
int i;
char addr[19] = { 0 };
char name[248] = { 0 };
dev_id = hci_get_route(NULL);
sock = hci_open_dev( dev_id );
if (dev_id < 0 || sock < 0) {
perror("opening socket");
exit(1);
}
len = 8;
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
if( num_rsp < 0 ) perror("hci_inquiry");
for (i = 0; i < num_rsp; i++) {
ba2str(&(ii+i)->bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(name),
name, 0) < 0)
strcpy(name, "[unknown]");
printf("%s %s\n", addr, name);
}
free( ii );
close( sock );
return 0;
}
i build code above by
gcc -o simplescan simplescan.c -lbluetooth
it is successfully
i got a binary(X86 PC) and i can use it to driver Bluetooth dongle to scan my own cellphone in PC.
still this step ,everything is good ,but I want build this code for ARM,
so I change the gcc --->arm-linux-gnueabihf-gcc
I have test this toolchain already ,for a "helloword" and 'read UART',using this toolchain is no problem .
but when I do # arm-linux-gnueabihf-gcc-o simplescan simplescan.c -lbluetooth. get something wrong.
it shows asm/xxx.h NO such file. (xxx here means so many files ).
I try to use CMD "locate" to search this asm/xxx.h file ,but there are so many asm/xxx.h file with the same name in my PC ,how can I select suitable one? DO I need ARM-Linux source code to build ?
I have no idea now ,please help me , thank you very much !

thanks for the answer of Parthiban!
I set the sysroot to the bsp,then successfully!
you should make sure that Bluetooth.so is exist in the BSP, and the head file below also!
bluetooth.h cmtp.h hci_lib.h l2cap.h sco.h sdp_lib.h
bnep.h hci.h hidp.h rfcomm.h sdp.h
ask Freescale or other chip vendor to get a yocto toolchain for your ARM chip!
root#yjppc:/a_work# $CC -o simplescan simplescan.c --sysroot /opt/myir-imx-fb/4.1.15-2.0.1/sysroots/cortexa7hf-neon-poky-linux-gnueabi/ -lbluetooth
root#yjppc:/a_work# ls
apps material simplescan simplescan.c

Related

Bluetooth C program cannot find library -lbluetooth

I am using this tutorial to learn how to use bluetooth in c on my raspberry pi:
https://people.csail.mit.edu/albert/bluez-intro/c404.html
I am currently trying to get running simplescan.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int main(int argc, char **argv)
{
inquiry_info *ii = NULL;
int max_rsp, num_rsp;
int dev_id, sock, len, flags;
int i;
char addr[19] = { 0 };
char name[248] = { 0 };
dev_id = hci_get_route(NULL);
sock = hci_open_dev( dev_id );
if (dev_id < 0 || sock < 0) {
perror("opening socket");
exit(1);
}
len = 8;
max_rsp = 255;
flags = IREQ_CACHE_FLUSH;
ii = (inquiry_info*)malloc(max_rsp * sizeof(inquiry_info));
num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
if( num_rsp < 0 ) perror("hci_inquiry");
for (i = 0; i < num_rsp; i++) {
ba2str(&(ii+i)->bdaddr, addr);
memset(name, 0, sizeof(name));
if (hci_read_remote_name(sock, &(ii+i)->bdaddr, sizeof(name),
name, 0) < 0)
strcpy(name, "[unknown]");
printf("%s %s\n", addr, name);
}
free( ii );
close( sock );
return 0;
}
When I compile using this command:
gcc -o simplescan simplescan.c -lbluetooth
I get this error:
/usr/bin/ld: cannot find -lbluetooth
collect2: error: ld returned 1 exit status
EDIT: For some reason now when I try to compile the error has changed to this:
simplescan.c:5:10: fatal error: bluetooth/bluetooth.h: No such file or directory
#include <bluetooth/bluetooth.h>
I have read that BlueZ comes pre-installed on Raspbian, and I have the newest version, but I can't seem to find the bluetooth library folder or any of the .h files in it.
This tutorial might be old so things might have moved around.
Does the bluetooth library come preinstalled along with bluez? If so, where should I look to confirm?
If this library is not on my RPI where should I get it from?
That tutorial is out of date as BlueZ has moved on since then. Back in 2012 there was major development to move to new APIs
Then in 2017 8 tools were deprecated from Bluez.
The API's to use now are the mgmt API which focused on system level functionality and is documented at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/mgmt-api.txt
For application level, it is the D-Bus API's that you should be using. These are spread across a number of documents in: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc
There are not many C examples around. The examples in the source tree are for the D-Bus API and all use Python: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test
Looking at the code for the bluetoothctl tool might give you better examples. This code is available at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/client

How to get IP and MAC address in my C program for connected Wi-Fi user?

I try to create client application that can be installed into Wi-Fi Router(OpenWRT Attitude Adjustment 12.09)
Application must be written in C and implement OpenWRT daemon approach.
When any visitor turns Wi-Fi and connects to my SSID I need use his IP and MAC address in my C program.
How can I get IP and MAC address in my C program for any new connected users(devise)?
I started to try use arp command for any IP which already connected to router:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* ip = "192.168.1.101";
char output[255];
char command [255];
//system("arp -a");
sprintf(command,"%s %s %s","arp","-a",ip);
FILE* arp = popen(command, "r" );
int i = 1;
while (fgets(output, sizeof(output), arp) != 0) {
i++;
if ( i == 2 ) {
printf("%s",output);
char macAddress[18];
int index = (int)(strchr(output,'-')-output);
printf( "\n%d",index);
printf ("\n----%c", output[index-2]);
memcpy(macAddress, &output[index-2], 17);
macAddress[17] = '\0';
printf("\n%s",macAddress);
}
}
pclose(arp);
return 0;
}
system("arp -a"); works in Ubuntu but not for OpenWRT after Cross compile!
Maybe I need to choose other way?
thanks in advance for any help

How can i get screen resolution in c (Operating system QNX or Linux)

I am in a GUI development with QNX(screen resolution interdependent design)
How can i get screen resolution in c.
I am using QNX operating system.
Is it possible?
Is any OS function for this solution?
thanks
Assume you are using a device with a framebuffer (and have root access):
(taken from this answer: Paint Pixels to Screen via Linux FrameBuffer)
Also, as mentioned above, what graphics library you are using will make a lot of difference as this code will only tell you what the framebuffer is set to and not what the GUI code is using. So might not be useful at all. If you are not using X or any other graphics library, then you will probably need to be using the framebuffer, and you can see the rest of the answer for how to do that. (I strongly suggest you use DirectFB this will save you implementing a LOT of code).
Also, you could also use the gl drivers that turn up on most devices (inc. embedded ones) so this will also effect how you do what you require.
Are you using a SOC? Does the manufacturer have there own driver layer? That may work completely different and would probably come with it's own API to handle this.
But anyway, I hope this helps.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd == -1) {
perror("Error: cannot open framebuffer device");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Error reading fixed information");
exit(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Error reading variable information");
exit(3);
}
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
// Figure out the size of the screen in bytes
//
close(fbfd);
}
For a unix-like OS, you may use the library X11, but if you need cross-platform solution, try the GTK+.
A full code
// The C standart library
#include <stdlib.h>
// GTK+
#include <gtk/gtk.h>
#include <glib.h>
#include <glib/gprintf.h>
// X11
#include <X11/Xlib.h>
/*
Printing a current screen resoltion by using the GTK+3
https://en.wikipedia.org/wiki/GTK%2B
*/
int
print_screen_resolution_by_GTK(int argc, char *argv[])
{
GdkScreen *screen;
gint width, height;
gtk_init(&argc, &argv);
if ((screen = gdk_screen_get_default()) != NULL) {
width = gdk_screen_get_width(screen);
height = gdk_screen_get_height(screen);
g_printf("Current screen resolution: %dx%d (by used GTK+)\n", width, height);
}
return 0;
}
/*
Printing a current screen resoltion by using the libX11 (worked only for Unix-like OS)
https://en.wikipedia.org/wiki/X_Window_System
Based on:
https://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html
http://surfingtroves.blogspot.com/2011/01/how-to-get-screen-resolution-in-linux-c.html
*/
int
print_display_resolution_by_X11()
{
Display *display;
Window window;
XWindowAttributes xw_attrs;
if ((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "Failed to open default display\n");
return -1;
}
window = DefaultRootWindow(display);
XGetWindowAttributes(display, window, &xw_attrs);
printf("Current window resolution: %dx%d (by used X11)\n", xw_attrs.width, xw_attrs.height);
XCloseDisplay(display);
return 0;
}
int main(int argc, char *argv[])
{
print_screen_resolution_by_GTK(argc, argv);
print_display_resolution_by_X11();
return EXIT_SUCCESS;
}
A compilation
gcc -o main main.c `pkg-config --libs --cflags gtk+-3.0 x11`
A result (actual for my computer)
Current screen resolution: 1366x768 (by used GTK+)
Current window resolution: 1366x768 (by used X11)
You can simply use this function I created, it get screen size from your configuration files, split it, and then return 2 values (resolution as x and y)
I tried it on Ubuntu 20.04 and it works perfectly !
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned short *get_screen_size(void)
{
static unsigned short size[2];
char *array[8];
char screen_size[64];
char* token = NULL;
FILE *cmd = popen("xdpyinfo | awk '/dimensions/ {print $2}'", "r");
if (!cmd)
return 0;
while (fgets(screen_size, sizeof(screen_size), cmd) != NULL);
pclose(cmd);
token = strtok(screen_size, "x\n");
if (!token)
return 0;
for (unsigned short i = 0; token != NULL; ++i) {
array[i] = token;
token = strtok(NULL, "x\n");
}
size[0] = atoi(array[0]);
size[1] = atoi(array[1]);
size[2] = -1;
return size;
}
int main(void)
{
unsigned short *size = get_screen_size();
printf("Screen resolution = %dx%d\n", size[0], size[1]);
return 0;
}
If you have any question, do not hesitate ! :)

MAC address from interface on OS X (C)

This might be a stupid question and I apologize if it's already been addressed here, but I've searched quite a bit without much luck. I'm trying to get my interface's hardware address in C and I'm using OS X (x86-64). I know how to get it with ifconfig, but I want my program to get it automatically for any computer, well, at least OS X computers. I found another thread that posted this link which pretty much does what I want (with some modifications), but I can't make the iokit functions link in ld (my compiler is gcc). I tried adding the flags -lIOKit and -framework IOKit to the gcc command line, but I still get the same link errors. Here's a link to my code: header and source.
This little program will work without changes on OSX.
Code : (credits to Alecs King from freebsd list)
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int mib[6], len;
char *buf;
unsigned char *ptr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
if (argc != 2) {
fprintf(stderr, "Usage: getmac <interface>\n");
return 1;
}
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
if ((mib[5] = if_nametoindex(argv[1])) == 0) {
perror("if_nametoindex error");
exit(2);
}
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
perror("sysctl 1 error");
exit(3);
}
if ((buf = malloc(len)) == NULL) {
perror("malloc error");
exit(4);
}
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
perror("sysctl 2 error");
exit(5);
}
ifm = (struct if_msghdr *)buf;
sdl = (struct sockaddr_dl *)(ifm + 1);
ptr = (unsigned char *)LLADDR(sdl);
printf("%02x:%02x:%02x:%02x:%02x:%02x\n", *ptr, *(ptr+1), *(ptr+2),
*(ptr+3), *(ptr+4), *(ptr+5));
return 0;
}
You should, however, change int len; to size_t len;

How to get network adapter stats in linux/Mac OSX?

I'm looking for a way to get hold of network stats in C on Linux and MacOSX. Specifically, I need to monitor the number of bytes uploaded and downloaded from each network adapter on the system - I don't need to do packet inspection, or differentiate between protocols, just a 'total bytes' counter which I can poll at intervals would be fine. In Windows I can do this using the iphlpapi.dll library via GetIfTable (to list the network adapters) and GetIfEntry (to read the stats), but I can't find the Linux/OSX equivalents. My knowledge of C is fairly basic so I would appreciate a solution that isn't too involved. Any help would be much appreciated!
The Darwin netstat source code uses sysctl.
Here's some code that prints the number of bytes in and out on OSX:
#import <Foundation/Foundation.h>
#include <sys/sysctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/route.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int mib[] = {
CTL_NET,
PF_ROUTE,
0,
0,
NET_RT_IFLIST2,
0
};
size_t len;
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
fprintf(stderr, "sysctl: %s\n", strerror(errno));
exit(1);
}
char *buf = (char *)malloc(len);
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
fprintf(stderr, "sysctl: %s\n", strerror(errno));
exit(1);
}
char *lim = buf + len;
char *next = NULL;
u_int64_t totalibytes = 0;
u_int64_t totalobytes = 0;
for (next = buf; next < lim; ) {
struct if_msghdr *ifm = (struct if_msghdr *)next;
next += ifm->ifm_msglen;
if (ifm->ifm_type == RTM_IFINFO2) {
struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
totalibytes += if2m->ifm_data.ifi_ibytes;
totalobytes += if2m->ifm_data.ifi_obytes;
}
}
printf("total ibytes %qu\tobytes %qu\n", totalibytes, totalobytes);
[pool drain];
return 0;
}
I can't speak to OSX but on linux take a look at /proc/net/dev.
If you do 'cat /proc/net/dev' you should see statistics including 'bytes' - the total number of bytes of data transmitted or received by the interface. You can read the file within your own program.
EDIT:
I didn't read your whole question. This article should help you get started with /proc and has a section on /proc/net/dev.
Also, to list the interfaces you can call ioctl with the SIOCGIFCONF option. You can Google for a decent code example on how to loop through the returned data. Or you can simply pull it out of the /proc.net/dev data mentioned above, which should be easier.
on Linux:
low level: check /sys/class/net/eth0/statistics/
slightly higher level: ip -s link show eth0
graphical: iftop
interactive: iptraf

Resources