How to deal with linux kernel drivers (for newbies) - linux

I am trying to undestand how to USE linux kernel drivers. One day I wrote linux kernel module for handling interrupts from gpio. Built it with "make" command and loaded it with "insmod" and it worked. But now I am trying to use this ov5642 camera driver.I downloaded the source code. made "make" command in folder with sources and when it built I used "insmod" command to load it. It is now listed in already loaded modules list but I have got no idea how to get grabbed frames.
How can I make it work and access its output ?

In order to capture frames from the module, you need to "probe" your driver with a platform device (i.e. you have to create a platform device in order to call "ov5642_probe" function). If the probe function is being called, and ends successfully reaching to "return 0", you will get a print "Chip ID 0x5642 detected" in dmesg. (You can easily check weather the probe function is being called or not by putting a simple "printk(KERN ERR "### my probe function is being called")" at line number 935 in probe function and check in dmesg. If it is being called, you have to interface the camera properly in order to probe driver successfully.
If probe function fails (i.e. being called but not reaching till "return 0"), then there should be problem with reading the registers of ov5642. Check the i2c connections and power supplies of camera properly (and make sure its power on sequence is performed as mentioned in datasheet) if you get "Chip ID" other than 0x5642 or i2c read fails.
If the probe function is not being called, then you need to create a proper platform_device.
Assuming you are doing this on a custom board where ov5642 module is interfaced.
If you get "Chip ID 0x5642 detected" in dmesg, then you should try with "v4l-utils" package. There are many options available in v4l2-ctl command where you can set format, query capabilities, start stream, grab frame. If you are unable to install v4l-utils on your board, then, you should try https://gist.github.com/maxlapshin/1253534. You can also refer to Documentation/video4linux/ on lxr online or any kernel source offline if you are interested in developing a camera driver.
If you are a newbie, and you want to learn to deal with kernel drivers, refer to http://www.makelinux.net/ldd3/ and specially platform driver documentation under Documentation/driver-model/platform.txt on lxr for creating and probing a platform driver.

Related

IMA fails to detect existing TPM eventhough it exists and functions correctly

I’m currently trying to perform integrity measurement using a TPM (SLB 9670) on a Raspberry Pi 3 model B+.
I have the TPM installed and working properly since I can execute some basic commands like tpm2_getrandom() and so on. Now I want to perform an integrity measurement using IMA, and I have recompiled the new kernel with the following config:
CONFIG_SECURITY=y
CONFIG_SECURITYFS=y
CONFIG_INTEGRITY=y
CONFIG_IMA=y
CONFIG_IMA_MEASURE_PCR_IDX=10
CONFIG_IMA_AUDIT=y
CONFIG_IMA_LSM_RULES=y
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_READ_POLICY=y
CONFIG_IMA_APPRAISE=y
CONFIG_IMA_APPRAISE_BOOTPARAM=y
CONFIG_HW_RANDOM_TPM=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS_CORE=y
CONFIG_TCG_TIS=y
but the ima for some reason still doesn’t detect the TPM and gives the errors:
I have done some research and found out that maybe this is due to the fact that the ima get initialized before the TPM, so I have also tried to compile another version of the kernel where I change the code line in devices/clk/bcm/clk-bcm2835:
from:
postcore_initcall(__bcm2835_clk_driver_init);
to
subsys_initcall(__bcm2835_clk_driver_init);
But it still didn’t work.
Please help!
You are on the right path, I believe what is missing is the SPI & TPM kernel modules have to be configured to built-in. Take a look at this doc for the detailed steps.

Linux: writing to the i2c/SMBus

I have a problem with the i2c/SMBus on a Linux System with an Intel Apollo Lake processor. I am trying to read/write from/to an EEPROM but I face some issues. My EEPROM is located at the address 0x56, and I am able to watch the Bus with my Logic Analyzer.
When I try to read from the device via i2ctools (i2cget) the System behaves as expected. My issue occurs when I try to perform a write command via i2cset for example. i2cset ends with an error (Write failed). Because I am able to watch the Bus electrically I can also say that all lines stay HIGH and the Bus is not touched. I was able to activate the dev_dbg() functions in the i2c driver i2c_i801 and when I perform i2cset I am able to find (dmesg) the debug message:
[ 765.095591] [2753] i2c_i801:i801_check_post:433: i801_smbus 0000:00:1f.1: No response
When running my minimal I²C Python code using the smbus2 lib, I get the following error message and the above mentioned debug message:
from smbus2 import SMBus
bus = SMBus(0)
b = bus.read_byte_data(86,10) #<- This is performed
b = bus.write_byte_data(86,10,12) #<- This is not performed
bus.close()
Error:
File "usr/local/lib/python3.8/dist-packagers/smbus2-0.4.0-py3.8.egg/smbus/smbus2.py", line 455, in write_byte_data
ioctl(self.fd, I2C_SMBUS, msg)
OSERROR: [Errno 6] No such device or adress
A big hint for me is that I am not able to perform a write command in the address space form 0x50 to 0x57. My guess is that some driver locks the address space to prevent write command to that "dangerous" area.
My question is: "Does anyone know this kind of behavior and is there a solution so that I can write to my EEPROM at address 0x56? OR Is there a lock surrounding the i2c adress space from 0x50 to 0x57 and who is my opponent?"
I am kind of a newbie to the whole driver and kernel world so please be kind and it is quite possible that I made a beginner mistake.
I would appreciate hints and tips I can look after surrounding my problem.
It seems that I found the cause of my problem. In this Forum post is described that Intel changed a configuration Bit at the SMBus controller.
OK, I know what's going on.
Starting with the 8-Series/C220 chipsets, Intel introduced a new
configuration bit for the SMBus controller in register HOSTC (PCI
D31:F3 Address Offset 40h):
Bit 4 SPD Write Disable - R/WO.
0 = SPD write enabled.
1 = SPD write disabled. Writes to SMBus addresses 50h - 57h are
disabled.
This badly documented change in the configuration explains the issues.
One Challenge is, that to apply and enable changes to the SPD-write Bit the System needs to be rebooted. Unfortunately while rebooting the BIOS will change the Bit back to the default. The only solution seems to be an adaption in the BIOS.
For me, this issue is resolved. I just wanted to share this information in case someone faces the same issues.

Linux Kernel 3.3 not registering missed beacons with connected Access Point

I'm using linux kernel 3.3 (I cannot upgrade my kernel, sorry!) and am trying to use the wpa_cli utility to monitor the status of my WiFi connection. I'm using an Edimax WiFi dongle to connect to a wireless access point.
I expect to see something like this:
# wpa_cli status
Selected interface 'wlan0'
wpa_state=SCANNING
ip_address=XXX.XXX.XXX.XXX
address=XX:XX:XX:XX:XX:XX
Or the same thing but with wpa_state=COMPLETED, depending upon my connection status.
Parsing the this text output allows me to see if my wireless connection is active or scanning. However, I have noticed that after powering off my access point wpa_state=COMPLETED is still being returned. Using the command:
# iwlist wlan0 scanning
Forces a scan and wpa_state will occasionally be correct, but usually (99%) not.
Here is my /etc/wpa_supplicant.conf:
ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
country=US
network={
ssid="myssid"
psk="mypsk"
key_mgmt=WPA-PSK
eap=
}
After some investigation, I believe something weird is happening causing the kernel to return a cached version of the AP list. I am using the RTL8192cu driver. I've already looked at this issue, and it is not the same as mine.
My belief is that the issue may be somewhere in the kernel. In the file net/mac80211/scan.c, at line 214 in function ieee80211_scan_rx, I see a bssid from the BSS of my AP appear (when AP has power) and get put via ieee80211_rx_bss_put (here). At this point, it is returned in scan results and wpa_supplicant causes the MLME layer in the kernel to authenticate and connect with that AP. However, after disconnecting AP power, I never see the MLME layer relinquish it's atomic_t hold on that BSS. This causes the BSS to never to unlinked in the function
cfg80211_bss_expire at the end of a scan (cfg80211_wext_giwscan), in file net/wireless/scan.c, line 205 (here).
Specifically, I would like to know why the atomic used to "hold" a BSS is not decremented on power removal from the AP - causing linux to miss sufficient beacons for a disconnect? Or, is there some configuration with wpa_supplicant I need to add to have the MLME kernel layer decrement it's hold on the BSS, or is this clearly a kernel bug?
I've already tried:
# wpa_cli bss_expire_age 10
# wpa_cli bss_expire_count 2
and have not resolved my issue.
So after a lot of digging, I found that the issue was because of the kernel's rtlwifi driver. To me, it looks like the rtl8192cu driver was suppose to be responsible for handling missed beacons, by calling the function ieee80211_beacon_loss, but that call is nowhere to be found. I removed support for IEEE80211_HW_BEACON_FILTER in the rtlwifi driver and the issue has been fixed.
This patch is essentially the same changes that I made, and the comments in this file are part of what led to me this answer.

Linux low level driver - how to receive multiple commands for a device

I had written a linux scsi low level driver for cdrom. Am able to receive commands one by one from application and am testing it using sg3-utils.
Now I want to receive more than one command while serving the first one.?
for this I tried changing the struct scsi_host members can_queue and cmd_per_lun to some big values like 40, even though not able to receive multiple commands.
Is there any way to test multiple command reception in existing drivers like scsi_debug ?
Please give a little more information ... when you say "receive commands" that implies you are a target. Maybe you mean "sending commands".

How to create an event# device for a virtual input device (/dev/input/js3) in linux kernel module?

i am writing a linux kernel module which takes N of real /dev/input/js# devices and proxifies them as a single /dev/input/js3 device. Currently my module is creating /dev/input/js3 just fine, jstest is happy with it, but not the real applications. I guess (strace'd) it is so because i have no matching pair of /dev/input/event# for my virtual js3 device. How do i create one from my module?
Here is my module's source, which probably has numerous of issues, but mostly working: https://github.com/iamtakingiteasy/unijoy/blob/master/unijoy.c
Here is an example, you can use
1. class_create to create the class specified for the device,
2. device_create to create the device node
3. cdev_init to initialize and
4. cdev_add to add the device to the /dev list
For example you can refer the below link :Create a device node in kernel module

Resources