Opening USB device for communication in C - c

The short version. When trying to open a USB device using the open() function in the fcntl.h header, the program freezes
Now the slightly longer version. I am trying to interface with a time of flight sensor (TeraRanger Evo 60m). I am working on a mac running Big Sur 11.2.1. Using ls -l /dev/tty.* i have located the device path to be /dev/tty.usbmodem00000000001A1.
I have taken my code and heavily simplified it to isolate the issue I'm currently facing
#include <fcntl.h> // open
#include <stdio.h> // print
int main()
{
// /dev/tty.usbmodem00000000001A1
char *device = "/dev/tty.usbmodem00000000001A1";
printf("Start\n");
int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
if(fd < 0)
{
perror(device);
return -1;
}
printf("Opened\n");
return 1;
}
When trying to open the device, the program freezes. There is no error printed to help me debug either. I have successfully connected to and received messages from another USB device I own by only changing the device path. Yet, this sensor make the code freeze.
I may also be useful to know that using the screen /dev/tty.usbmedem00000000001A1 115200 terminal command shows the output expected from the sensor. This means the device is properly functioning and it can be connected to but i have messed up my code somehow. I would greatly appreciate any help y'all can provide. Thank you!

Related

C serial program using keyboard and monitor instead of serial port /dev/ttyUSBX

I am trying to write a program that accepts keyboard input and puts the output on the screen but acting as if it is a serial port. I am not sure this is even doable. My current code for the serial port that works is:
int fd;
char *portname;
char buf[255];
struct termios tty;
portname = "/dev/ttyUSB0";
// opening serial port
fd = open(portname, O_RDWR | O_NOCTYY | O_SYNC );
//writing to serial port
write (fd, "hello!\n", 7);
//Reading from serial port
read (fd, buf, 255)
So, is it possible that instead of setting portname as /dev/ttyUSB0 I set it as something else (e.g. /dev/stdin?) and then get the exact same UART functionality but keyboard is set as input and screen as output?
Thank you for your help.
UNIX/Linux sets up stdin (fd 0), stdout (fd 1) and stderr (fd 2) already open to the terminal (whether serial line with real hardware terminal, virtual console or graphics terminal) your keyboard and screen are connected to. It's available for termio control and as a special device filename /dev/tty the termios routines termios(3) man page operate on the already open fild descriptor, which allows getting of terminal driver attributes, turning off canonical mode and later resetting the values at end of your program.
You simply read/write as normal, in POSIX everything's a file, whether it's a serial line, disk, terminal emulator is abstracted away, to the process doing I/O by the OS kernel.

Set wireless channel using netlink API

I am developing a WiFi tool in Ubuntu Linux 12.04 environment and I need to switch the WiFi interface between different channels.
Currently I found the solution in Wireshark source code ws80211_utils.c in function called ws80211_set_freq but I do not know how to implement it into my source code and which libs to include and how to compile so I could test it.
The problem is that there are too many arguments and flags you have to use. Also, this is the first time I develop a netlink wifi tool.
If there are any good manuals available where to start and how to use netlink calls for WiFi please provide me with the link.
Thanks a lot i advance!
In current Linux versions, nl80211 is the right way to "talk" to the wireless subsystem. Be aware that you cannot arbitrarily set a channel with every driver and every operating mode (master, client, monitor etc.) Some drivers allow a channel change only when the corresponding interface is "down". In modes such as client ("managed"), the channel cannot be set at all because it is defined by the access point.
Also note that not all wireless device drivers use mac80211/cfg80211. For those drivers not using it, you either have to use the old wireless extensions API or (even worse) a driver-specific proprietary API.
Sadly, there seems to be no up-to-date and complete documentation of the nl80211 interface. Please correct me if I am wrong!
Your approach of looking into the source code of other programs seems to be a reasonable way. You could also use the source code of the iw command line utility. iw has an option to set the channel:
$ iw --help
Usage: iw [options] command
Options:
--debug enable netlink debugging
--version show version (3.2)
Commands:
…
dev <devname> set channel <channel> [HT20|HT40+|HT40-]
…
In iw's phy.c, line 91ff. you can find the code called when iw wlan0 set channel is executed. However, this code is definitely not easy to read. It looks like the
NL80211_CMD_SET_WIPHYcommand in conjunction with the NL80211_ATTR_WIPHY_FREQ attribute is the way to go.
In this SO answer you can find a skeleton program for using nl80211. Also, the code of Aircrack-ng (src/osdep/linux.c, function linux_set_channel_nl80211) could act as a blueprint.
The accepted answer is currently correct, but there's no example code posted yet which solves the OP's question (even if nearly 4 years late), so I thought I would add this here for any future search engine users. It's adapted from this SO question and the specific Aircrack-ng file (/src/aircrack-osdep/linux.c, line 1050) that were both previously mentioned.
#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <linux/nl80211.h>
int main(int argc, char *argv[])
{
/* The device's name and the frequency we wish to set it to. */
char *device = "wlan1";
int frequencyMhz = 2442;
/* Create the socket and connect to it. */
struct nl_sock *sckt = nl_socket_alloc();
genl_connect(sckt);
/* Allocate a new message. */
struct nl_msg *mesg = nlmsg_alloc();
/* Check /usr/include/linux/nl80211.h for a list of commands and attributes. */
enum nl80211_commands command = NL80211_CMD_SET_WIPHY;
/* Create the message so it will send a command to the nl80211 interface. */
genlmsg_put(mesg, 0, 0, genl_ctrl_resolve(sckt, "nl80211"), 0, 0, command, 0);
/* Add specific attributes to change the frequency of the device. */
NLA_PUT_U32(mesg, NL80211_ATTR_IFINDEX, if_nametoindex(device));
NLA_PUT_U32(mesg, NL80211_ATTR_WIPHY_FREQ, frequencyMhz);
/* Finally send it and receive the amount of bytes sent. */
int ret = nl_send_auto_complete(sckt, mesg);
printf("%d Bytes Sent\n", ret);
nlmsg_free(mesg);
return EXIT_SUCCESS;
nla_put_failure:
nlmsg_free(mesg);
printf("PUT Failure\n");
return EXIT_FAILURE;
}
Compile this with gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0).
Once executed, check the frequency/channel of your device with e.g. iw wlan1 info or iwconfig. There's no serious error checking here, so all you will notice is if the message was sent or not. Hopefully this helps anyone like me making the transition from Wireless Extensions to cfg80211 and nl80211.

open system call - Linux

Trying to open tty port using open system call. HOw do i know if this port is being used by another application in case the open system call returns -1?
DO not find error codes for the same.
a call to open() won't give you an error if the file is already open.
Howerver, you can try to analyze the output of the linux lsofcommand:
lsof /dev/ttyS0
It will return information about the processes that opened the given file (in this case: /dev/ttyS0).
(I've tested this a few times so I'm not sure about it, but lsof seems to return 0 if the file is opened by a process and return 1 if no process has opened it. This could be an indication, however I would suggest you really analyze the output of the command itself)
#include <errno.h>
#include <stdio.h>
#include <strcing.h>
int main()
{
if(open("/dev/ttyS0", O_RDWR))
printf("errno = %s\n", strerror(errno));
return errno;
}
see this link in order to figure out what the error code is.

to keep files after kernel rebooting

i need to use reboot() system call (to reboot the kernel 2.6.29 with ARM) and i tried the code below:
#include <stdio.h>
#include <linux/reboot.h>
#include <unistd.h>
int main()
{
reboot(LINUX_REBOOT_CMD_RESTART);
}
it works well! but what im wondering is after rebooting the kernel im loosing the files being saved.
i mean if use this code, "url" file is not saved after reboot.
int main()
{
FILE *pFile = fopen("url", "a"); // for .txt file
// write to file/read from file ... etc
fclose(pFile);
int fdUART = open("/dev/ttySAC0", O_RDWR | O_NOCTTY | O_NDELAY);
// some operations on UART port
close(fdUART);
/* Ethernet raw package process*/
/* Char dev driver open and communicate with FPGA fifo */
/* so on */
reboot(LINUX_REBOOT_CMD_RESTART);
}
and am using the UART, Ethernet, char drivers and just would like to know reboot() call systems's effect to my system.
any help highly appreciated thanks.
You've written in the comments that the file system is cramfs.
From the Wikipedia page for cramfs:
The compressed ROM file system (or cramfs) is a free (GPL'ed) read-only Linux file system designed for simplicity and space-efficiency. It is mainly used in embedded systems and small-footprint systems.
Note that it's read-only: that means your changes won't be preserved.
You'll need to write to persistent storage to have your changes preserved.

libpcap : No Wireless Devices detected

I want to capture packets going out of my machine, and I'm using libpcap (version 1.0.0-1) for the same. The problem is, that a basic program like this -
#include <stdio.h>
#include <pcap.h>
int main(int argc, char *argv[]) {
char *dev, errbuf[PCAP_ERRBUF_SIZE];
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "%s\n", errbuf);
return (2);
}
printf("Device : %s\n", dev);
return (0);
}
does not seem to display the wireless interface. Everytime I compile and run the program, it detects eth0. How can I make it capture the wireless interfaces as well?
pcap_lookupdev() returns the default networking device on the system, which is usually the first device listed. pcap_findalldevs() returns an enumeration of all devices in the system, which you can use to select a device and capture from it.
try using pcap_findalldevs(). i guess pcap_lookupdev() matches the first entry in the list is suitable interfaces
As others have stated, pcap_lookupdev() simply returns the first device found. You need to use pcap_findalldevs() to build a list of all available devices, then prompt the user to pick one (or let the user specify a number n on the command line, and then use the _n_th device).
But, if this is just a quick-and-dirty test program, you can find out the interface name and code it directly into your program. You can use ifconfig or tcpdump -D to find out the interface names on your system, then make a call like pcap_create("en1", errbuf).

Resources