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
Related
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
I have weird problem. I try to communicate with ifm AY1020 via modbusTCP using libmodbus from PC.
My code looks as follow:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus/modbus.h>
int main()
{
modbus_t *ctx;
uint16_t *tab_reg;
int rc;
int i;
ctx = modbus_new_tcp("192.168.1.250", 502);
modbus_set_debug(ctx, TRUE);
tab_reg = (uint16_t *) malloc(5 * sizeof(uint16_t));
memset(tab_reg, 0, 5 * sizeof(uint16_t));
if (modbus_connect(ctx) == -1)
{
fprintf(stderr, "Connection failed: %s\n",modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_registers(ctx, 3002, 2, tab_reg);
if (rc == -1)
{
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
for (i=0; i < rc; i++) {
printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
}
modbus_close(ctx);
modbus_free(ctx);
}
Thanks to debug I was able to get the frame that is generated in modbus_read_registers function:
[00][01][00][00][00][06][FF][03][0B][BA][00][02]
And I get this
ERROR Gateway path unavailable
Gateway path unavailable
After analysis you can find that device id in that frame is FF, but according to this error PLC expects 1.
Going further if during debugging I force change this value from FF to 01 everything works fine. It looks like it assign wrong ID.
I would be grateful for any help, advice, solution.
Best,
Paweł
Looking at the Man
You should call modbus_set_slave to set a specific destination device.
TCP
The slave number is only required in TCP if the message must reach a device on a serial network. The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to restore the default value.
Emphasis mine
Your code should be
modbus_set_slave(ctx, 1);
rc = modbus_read_registers(ctx, 3002, 2, tab_reg);
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 ! :)
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;
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