Get Wi-Fi signal strength via libnl? - linux

I want to read the Wi-Fi signal strength from a userspace program on Linux.
As /proc/net/wireless is not available on the system, I have found out that libnl should be used to acquire the information.
Compared to just reading a value in /proc, communication via libnl seems to be very complicated. I have read various documentation, but I'm still not sure exactly what to do.
Can anyone give an example on how to read the Wi-Fi signal strength via libnl?

If you already have iw library https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git.
You can type sudo iw dev wlan0 scan (instead of 'wlan0' interface you can type the one you need) in your terminal. There is signal line that I think you are interested in. All the work for getting this information to user is made in scan.c file of iw library. So you can just check the source code and get some tips from there.

Related

How to read the i2c adapter class (e.g. I2C_CLASS_DDC) from userspace (linux i2c-dev)?

Outside of Laptops, changing e.g. brightness of monitors requires DDC/CI. This is best done in userspace, I believe. Loading i2c-dev (kernel module) gives access to i2c-buses under /dev/i2c-<number>. Unfortunately not just monitors supporting DDC/CI have i2c-buses and it is far from ideal to read/write on unrelated buses, while trying to find which connects to what.
It seems that i2c bus adapter drivers already categorize their buses: e.g. I2C_CLASS_DDC for exactly what I’m looking for.
Is there any way to see the adapter class of a i2c-dev device?
(Or equally good: any way to match the device I want to talk to for DDC/CI from X11 workspaces or similar?)
You can try to look at ddccontrol:
ddccontrol -p
This utility scan I2Cs and somehow detects which are connected to monitors.
You can examine it's source code and find solution.
P.S.
This may be not an answer, but, sorry, I have not enough "reputation" to write a comment.

Linux: access i2c device within board_init function

(iMX6 SOC running Linux 3.0)
I need to run a few I2C transactions in my board_init function. I tried calling i2c_get_adapter, then i2c_transfer, those being available in kernel mode, but i2c_get_adapter returns NULL. It's already called imx6q_add_imx_i2c, which is a wrapper around platform_device_register_full, but that isn't enough.
I can manipulate GPIO in board_init by calling gpio_request to obtain access, and gpio_free at the end. Is there something analogous to those functions for i2c?
--- added details ---
I've got a LAN9500A USB 100Base-T Ethernet MAC connected to a LAN9303 3-port switch with a virtual PHY. The MAC has a GPIO reset line that has to be turned off before it will spring to life and enumerate on the USB. That's done in board_init because it's completely nonstandard, so we don't want to patch the stock driver to manipulate some GPIO that's not part of the device.
The problem I'm having is that even though the MAC is permanently attached to the VPHY, it's not noticing it's connected, and an "ip link show eth1" command shows NO-CARRIER. I found I can kickstart it by unmasking the VPHY's Device Ready interrupt via I2C, but I also have to mask it immediately, or I get infinite interrupts. That's not the right solution, but Microchip has been no help in showing me a better way. But we don't want to patch the MAC driver with code to fiddle with the PHY.
There is no PHY driver for this part, and the MII interface to the VPHY doesn't include any interrupt-related registers, so it must be done through I2C. Writing a PHY driver just to flip a bit on and off once seems a lot of trouble, especially for a newbie like me who's never written a driver before.
I can do it in Python in a startup script, but that, too, seems like a heavyweight solution to a lightweight problem.
That's a wrong approach. Board file supposed to register device drivers and pass important information to them, rather than act as a device driver itself. I'm not sure if what you're trying to do is even possible.
If you really need to extract something from your I2C device on a very early stage - do that in the bootloader and pass the data to kernel via cmdline (U-boot, by the way, has I2C support for a quite some time). Then later, kernel might do appropriate actions depending on what you have passed to it.

How can I write a kernel module that can keep track of the SCSI commands sent to a particular device?

Given a SCSI device as input, I am trying to implement a kernel module that can :
Get the list of SCSI commands sent to that particular device and count the number of times that command was given.
How do I proceed to implement this?
I am a beginner at programming kernel modules, In fact I have only written a "Hello, World" program till now.
I believe there is already debugging and logging support on device driver side.
As a startpoint you should investigate the driver in the linux kernel which starts here:
https://github.com/torvalds/linux/blob/master/drivers/scsi/scsi_module.c
And for the debugging you find this one:
https://github.com/torvalds/linux/blob/master/drivers/scsi/scsi_logging.c
And it is always a good idea to read the manual first! Give it a chance here:
https://www.kernel.org/doc/Documentation/scsi/
If you can't get logging activated, you should come back and ask a more specific question. But I believe you have no need to write your own logger at all.
From http://www.theunixway.com/2013/10/ol56-enable-additional-scsi-logging-or.html
Enabling scsi logging on kernel:
sysctl -q -w dev.scsi.logging_level=<N>
or
echo <N> > /proc/dev/scsi/logging_level
N is a bit field which contains different categories of logging information. Please refer to the documentation of the actual kernel driver version you use.

Getting ARM/WM8350 audio and power management working in linux

I have a rooted Sony prs900, running a linux 2.6.23 #2 PREEMPT kernel, for ARMv6. (Montavista linux kernel). I'm having problems with figuring out how power management works, both for running the system and for powering up and down the audio port.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
It's worth a little money for help, say $100 paypal donation to an email account, (or more if this takes a long time...) for the first person able to explain to me how to do them in a way that works.
Eg: read battery status, and change some power modes like getting the audio amplifiers to power up/down so that the audio played to /dev/dsp (oss emulation) actually comes out as sound rather than just being consumed by the chip and ignored...
The actual sony kernel, and binary packages of cross compiler tools are located on the main page. Actual kernel sourcecode is also available.
What I have learned so far myself :
The sony is using a wolfson micro WM8350 audio driver and battery charger/power management chip for all the system's power; eg: it can power down/up the SD memory cards, send more power to the cpu, power up audio amplifiers, etc. See: WM8350 Datasheet.
Pretty much, the whole problem revolves around getting the WM8350 kernel drivers to work...
Although the company brags quite a bit about it's support under linux, they don't have any application notes or examples that are actually helpful that I can find, other than the datasheet. I suspect the kernel drivers I have are beta code, because they don't seem to be behaving well (several error messages in the kernel log about wm8350 registers not being readable happen at every boot even when running only the sony's native software...).
The kernel driver's source-code of most interest are in: linux-2.6.23_091126/drivers/mxc/pmic/{core,wm8350}
Notice, the wm8350 is a competitor to the MC14783, but the linux kernel drivers use the same {core} driver source code for both chips; The sony ONLY has the wm8350 on it -- there is no MC14783 present.
The code that I most want most desperately to understand how to make operate is found in the subdirectory {wm8350}, eg: wm8350/wm8350pm/power_supply_sysfs.c.
I want the audio to fire up too, but 'm not quite sure where the pertinent audio amplifier code is yet...
Very clearly the wm8350pm code is designed to export a /sys directory interface; right now /sys is mounted and operational on the system; but I'm not very familiar with the semantics of these newer style interfaces... they aren't quite like the old APM power interfaces for Linux laptops...
First I checked the obvious:
If I do a "cat /sys/power/state" it returns the word "mem" and nothing else.
The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
Doing a find /sys -iname "wm8350" reveals a handful of directories with the patterns:
wm8350-rtc , wm8350-pmic , wm8350-bl , wm8350-power , wm8350-led
wm8350-hifi-dai , wm8350-codec
wm8350-imx32ads.0
So, I do an ls-l on each directory, and look for actual files rather than symbolic links or subdirectories, and what I find are stock useless writable files: bind, unbind, uevent,
and a very few read only files: pmic_reg, dapm_widget, modalias, codec_reg which aren't very helpful.
It's no surprise that:
Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/modalias gives "wm8350-ebx5016-audio"
Doing: cat /sys/devices/platform/wm8350-imx32ads.0/modalias gives "wm8350-imx32ads"
and since audio is off... Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/dapm_widget reveals the audio state:
Headphone Jack: Off
Line In Jack: On
Mic Bias: Off
Left DAC: Off
Right DAC: Off
... (all else off and omitted except )...
EBX5016-hifi: PM State: D3hot
The last two files, I expect should do wm8350 chip register dumps... and one did.
Doing: cat /sys/devices/wm8350-pmic/pmic-reg causes a long pause, then nothing is printed.
but:
Doing: cat /sys/devices/wm8350/platform/wm8350-ebx5016-audi/wm8350-codec/codec_reg does prints a list of registers up to e8 which is just a few bytes larger than the datasheet says the chip should be (0x00 to 0xe6).
I tried using a python program to play wav files, (works on my desktop computer), and I noticed that /dev/dsp does open, the mixers DO set volume levels, and nothing comes out. So -- the audio driver is not able to enable the sound amplifiers on it's own automatically.
There are no alsa sound files in /dev, nor are any alsa tools found on the embedded machine... so I assume Sony is strictly using OSS /dev/dsp and /dev/mixer.
There is only one other access point I can find to the ws8350:
There IS a device driver /dev/wm8350.
That driver created by the source code in subdirectory wm8350/wm8350_reg.c ; in theory it should be able to read and write to all registers using ioctls() calls from a user space. However, something appears grossly wrong with it, for I wrote a test program to read the wm8350 registers... and most of the registers return error messages rather than allowing to be read, including the most pulic ID registers (0x00, 0x01) etc.
So, I'm quite stuck. Pointers, thoughts, hints, are quite desired.
I would like to change your question a little bit.
How does Linux ASOC (alsa system on chip) power management work?
I will answer this and then give some hints on using this specific chip.
.. If I do a cat /sys/power/state it returns the word "mem" and nothing else. The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
You need to get an understanding of the Linux driver model. Hardware in Linux is structured like a tree. The rational is that things must be powered up/down in specific sequences. For instance, you should not power down the PCI bus controller before powering down the PCI peripherals. Linux builds a tree of hardware and each driver (code) and device (data/actual hardware) has specific call backs/function pointers which handle some specific tasks.
probe - Are you there? Determines actual hardware/device is present.
remove - Shuts down device. Module removal, power off, etc.
suspend - going to sleep.
resume - waking up.
Three and four may look interesting to you. Now, to read about what /sys/power/state is about. The text mem, means that suspend to memory is supported by your system. In this mode, Linux does these steps,
Find first lowest level active bus.
suspend devices on that bus.
suspend bus and de-activate.
If a bus is active go to step 1.
Set CPU to low power state (suspend to RAM).
This is not quite the full story. A few devices may support a wake-up. They will have extra call-backs to enable waking the system from sleep modes. Read the documentation to find out about this.
That is general power management and driver/device structure. Now, how is the ASOC (alsa system on chip) structured?
There are typically three drivers/devices that get stitched together.
Codec - The wm8350 in your case. This includes audio amplifier drive circuitry and can include sound mixing and source controls. Supports digital to analog and analog to digital, typically through an i2s interface. The i2s is not the only interface. Usually a register bank is controlled through a secondary interface; i2c in the wm8350 case.
DAI - Refer to chapter 1.2.18.1 of the iMx31 reference manual; the hardware is called the SSI by Freescale. The next chapter on the AUDMUX is also useful to understand audio support on the iMx31/32.
Machine file - this is the board specific routing. It hooks the DAI to the codec and is the parent of both. It provides board clocking information and other specific configuration. For instance, it may use the AUDMUX to route the physical pins to the SSI block.
An i2c (or SPI) interface from the codec driver to send control commands to the coded chip. Some chips might uses a wacky i2s interface or something else for control (but not in your case).
Now if you understood this, you will see that some features of the wm8350 seem to break the Linux model. The DAI interface can be stopped (digital audio), but the i2c interface must remain alive to program the registers related to the power functionality in the codec/PMIC (power management IC).
The latest WM8350 calls the IC a multi-function device and support was introduced in 2.6.35. The initial support may not have included the WM8350 features. Unfortunately, without some details on the layout of the Sony prs900 board, it would be difficult to know how to use the WM8350 PMIC functionality. The code will involve the iMx31 CPU, the WM8350, the i2c connection, and possibly some power supply circuitry.
For certain, you can just try echo mem > /sys/power/state and see what happens. If it works, you are lucky. The power/current consumption in sleep might not be optimal, but it will probably be hard to fix with the 2.6.23 kernel. You will want to look through the /sys directories for wake-up sources and possibly register these before issuing the suspend to memory command.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
From the above discussions, the battery and powerline status will probably be found through another device. However, the pmic_reg file may actually give the status if things are connected properly on the board.
The audio chip will use ALSA. You need to use either alsamixer or the command line amixer to set up audio routes through the codec, so the DAI channel (PCM from iMx32) is routed and sent to the speaker. To minimize power consumption, things are usually turned off by default. The /dev/dsp files are just OSS compatibility. This configuration will support ALSA natively. You are better off to use ALSA if possible.
Donate to the OSF and get a tax receipt, if this was helpful enough.

Command-line configurating a TTY device

My task at the moment is to port a driver for some 16550-compatible chip from QNX to Linux. The chip provides several UARTs, each one seen as a standard 16550 serial port, albeit with some extensions.
Now, in QNX, the whole device driver is packed into a standalone executable, that acts both as a driver and as an initial configurator for the provided UARTs (baud rates, loopback modes etc.) That is just natural in QNX because there device drivers run in user space and are little more than standard executables.
On Linux, OTOH, the driver is now implemented as a kernel module, loadable at will. More, that module is provided by the producer, so I would not want to modify or patch it too much.
For me, the remaining task is to provide some mechanism for setting up those UARTs' parameters. They are seen as /dev/ttyPREFIXX devices. I intend to do that through a standard C-programmed executable calling standard termios (ie tcsetattr() or ioctls) on the serial ports of interest.
Which leads me to the question: is my approach right? And, if yes, then how to achieve a persistent configuration? As I perceive the fact (from this example: http://www.easysw.com/~mike/serial/serial.html), the termios functions act on OPEN devices. In short: they open a device, they set up the parameters, they read or write, then close the port. After closing the port, is the configuration (baud rate etc.) lost? I hope it is not, because it is stored, already, into the hardware.
Can somebodey confirm to me that the configuration is persistent? And, if not, how to achieve that persistence, for the future applications that would open again that port and will expect it with some pre-established parameters? If not, should I modify the module kernel to accept some parameters and, then, do the configuration at the load time?
The approach that I intend for now is to write that C executable that opens the ports, sets up their configuration, then close the ports. I hope the latter applications will see the ports with the desired configuration.
Thank you.
You might want to have a look at stty and setserial. The venerable Serial-HOWTO (wow, when was the last time I actually recommended a HOWTO to anyone?) is probably also a good starting point.
Well, I found the answer here: http://www.gnu.org/software/libc/manual/html_node/Mode-Functions.html#Mode-Functions
Quote: "Although tcgetattr and tcsetattr specify the terminal device with a file descriptor, the attributes are those of the terminal device itself and not of the file descriptor. This means that the effects of changing terminal attributes are persistent; if another process opens the terminal file later on, it will see the changed attributes even though it doesn't have anything to do with the open file descriptor you originally specified in changing the attributes."
This clears the issue.

Resources