I've this driver:
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dai.h>
#include <sound/soc-dapm.h>
static const struct snd_soc_dapm_route max9880_dapm_routes[] = {
{"Mono out", NULL, "Mono Mixer"}
};
static struct snd_soc_codec_driver soc_codec_dev_max9880 = {
.component_driver = {
.dapm_routes = max9880_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(max9880_dapm_routes)
}
};
static struct snd_soc_dai_driver max9880_dai = {
.name = "max9880",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 1
}
};
static int max9880_platform_probe(struct platform_device *pdev)
{
int ret;
snd_printk(KERN_ALERT "1. platform probe");
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_max9880,
&max9880_dai, 1);
return ret;
}
static int max9880_platform_remove(struct platform_device *pdev)
{
snd_printk(KERN_ALERT "2. platform remove");
snd_soc_unregister_codec(&pdev->dev);
return 0;
}
static const struct of_device_id max9880_device_id[] = {
{ .compatible = "max9880" },
{}
};
MODULE_DEVICE_TABLE(of, max9880_device_id);
static struct platform_driver max9880_platform_driver = {
.driver = {
.name = "max9880",
.of_match_table = of_match_ptr(max9880_device_id),
},
.probe = &max9880_platform_probe,
.remove = &max9880_platform_remove,
};
module_platform_driver(max9880_platform_driver);
and I use insmod to load the module into the kernel. This all seems to work well, and I'm also able to do a rmmod without any problem. However I don't get any entries in /proc/asound/cards meaning that my module isn't recoqnized as a sound card. What am I missing?
Related
I want to understand why the probe function not being called.
what do I need to study to fix the problem with any USB type to auto-detected after the insertion automatically?
I use key a keyboard, kernel 5.6.3
Here's my code:
#include <linux/module.h> /*included for all kernel modules*/
#include <linux/kernel.h> /*included for KERN_DEBUG*/
#include <linux/init.h> /*included for __init and __exit macros*/
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
#define MY_USB_VENDOR_ID 0x045e
#define MY_USB_PRODUCT_ID 0x0800
static struct usb_device_id my_usb_table[] = {
{ USB_DEVICE(MY_USB_VENDOR_ID, MY_USB_PRODUCT_ID) },
{},
};
MODULE_DEVICE_TABLE(usb, my_usb_table);
static int
my_pdrv_probe(struct usb_interface *pdev, const struct usb_device_id *id) {
pr_err("Hello\n");
return 0;
}
static void my_pdrv_remove(struct usb_interface *pdev) {
pr_err("Bye\n");
}
static struct usb_driver mypdrv = {
.name = "my first usb driver",
.probe = my_pdrv_probe,
.disconnect = my_pdrv_remove,
};
// module_usb_driver(mypdrv);
static int __init my_pdev_init(void)
{
pr_err("Hello Guy\n");
/* Refister with kernel */
usb_register(&mypdrv);
return 0;
}
static void __exit my_pdev_remove(void)
{
pr_err("Bye Guy\n");
/* Unregister from kernel */
usb_deregister(&mypdrv);
}
module_init(my_pdev_init);
module_exit(my_pdev_remove);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sohaib Mohammed");
MODULE_DESCRIPTION("first usb driver module");
MODULE_VERSION("0.1");
The call to request_mem_region is failing (returns null).
I would say that the memory region I'm trying to access (GPIO starting at 0x3f20000) is being used.
I removed (rmmod) the module bcm28795_gpio but the request is still failing.
The modules I have loaded are (lsmod):
Module Size Used by
cfg80211 427817 0
rfkill 16018 1 cfg80211
snd_bcm2835 20511 0
snd_pcm 75890 1 snd_bcm2835
snd_timer 19160 1 snd_pcm
snd 51908 3 snd_bcm2835,snd_timer,snd_pcm
bcm2835_wdt 3225 0
uio_pdrv_genirq 3164 0
uio 8000 1 uio_pdrv_genirq
i2c_dev 5859 0
ipv6 347473 30`
cat /proc/iomem is returning the following:
00000000-3affffff : System RAM
00008000-007e7483 : Kernel code
00860000-0098e1ab : Kernel data
3f006000-3f006fff : dwc_otg
3f007000-3f007eff : /soc/dma#7e007000
3f00b840-3f00b84e : /soc/vchiq
3f00b880-3f00b8bf : /soc/mailbox#7e00b800
3f200000-3f2000b3 : /soc/gpio#7e200000
3f201000-3f201fff : /soc/uart#7e201000
3f201000-3f201fff : /soc/uart#7e201000
3f202000-3f2020ff : /soc/sdhost#7e202000
3f980000-3f98ffff : dwc_otg`
I think this issue is related to the Device Tree, but I'm not sure what do next.
The driver code:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/of_address.h>
#define DRIVER_NAME "tsgpio"
struct tsgpio_dev {
struct resource res;
void __iomem *virtbase;
} dev;
static const struct file_operations tsgpio_fops = {
.owner = THIS_MODULE,
};
static struct miscdevice tsgpio_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = DRIVER_NAME,
.fops = &tsgpio_fops,
};
static const struct of_device_id tsgpio_of_match[] = {
{ .compatible = "brcm,bcm2835-gpiomem" },
{},
};
MODULE_DEVICE_TABLE(of, tsgpio_of_match);
int __init tsgpio_probe(struct platform_device *pdev)
{
int ret;
ret = misc_register(&tsgpio_misc_device);
if (ret)
return ENODEV;
// Find address range in device tree
ret = of_address_to_resource(pdev->dev.of_node, 0, &dev.res);
if (ret) {
ret = ENOENT;
goto out_deregister;
}
// Request access to memory
if (request_mem_region(dev.res.start, resource_size(&dev.res),
DRIVER_NAME) == NULL) {
ret = EBUSY;
goto out_deregister;
}
/* Arrange access to our registers (calls ioremap) */
dev.virtbase = of_iomap(pdev->dev.of_node, 0);
if (dev.virtbase == NULL) {
ret = ENOMEM;
goto out_release_mem_region;
}
return 0;
out_release_mem_region:
release_mem_region(dev.res.start, resource_size(&dev.res));
out_deregister:
misc_deregister(&tsgpio_misc_device);
return ret;
}
int tsgpio_remove(struct platform_device *pdev)
{
iounmap(dev.virtbase);
release_mem_region(dev.res.start, resource_size(&dev.res));
misc_deregister(&tsgpio_misc_device);
return 0;
}
static struct platform_driver tsgpio_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(tsgpio_of_match),
},
.remove = __exit_p(tsgpio_remove),
};
static int __init tsgpio_init(void)
{
return platform_driver_probe(&tsgpio_driver, tsgpio_probe);
}
static void __exit tsgpio_exit(void)
{
platform_driver_unregister(&tsgpio_driver);
}
module_init(tsgpio_init);
module_exit(tsgpio_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Emanuel Oliveira");
Output from dmesg:
[ 1745.126636] tsgpio: init
[ 1745.130025] tsgpio: probe of 3f200000.gpiomem failed with error 16
Thank you!
I was testing the network hook code given in https://en.wikipedia.org/wiki/Hooking . My kernel version is 3.11.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
/* Port we want to drop packets on */
static const uint16_t port = 25;
/* This is the hook function itself */
static unsigned int hook_func(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *)){
struct iphdr *iph = ip_hdr(*pskb);
struct tcphdr *tcph, tcpbuf;
if (iph->protocol != IPPROTO_TCP)
return NF_ACCEPT;
tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), sizeof(*tcph), &tcpbuf);
if (tcph == NULL)
return NF_ACCEPT;
return (tcph->dest == port) ? NF_DROP : NF_ACCEPT;
}
/* Used to register our hook function */
static struct nf_hook_ops nfho = {
.hook = hook_func,
.hooknum = NF_INET_PRE_ROUTING,
.pf = NFPROTO_IPV4,
.priority = NF_IP_PRI_FIRST,
};
static __init int my_init(void)
{
return nf_register_hook(&nfho);
}
static __exit void my_exit(void)
{
nf_unregister_hook(&nfho);
}
module_init(my_init);
module_exit(my_exit);
But after loading , the above code is freezing the system. Can anybody please tell, what is the reason for that?. I think that the above code might have already tested in some lower versions of kernel. So I doubt, some kernel parameters or features have been changed.
The following sample code works fine under linux using g++4.8.2, using boost1_56. However, I get a strange linker error under MacOS X (Yosemite) using clang:
ld: internal error: atom not found in symbolIndex(__ZNSt3__112__hash_tableINS_17__hash_value_typeIKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEN15FRUIT_TUPLES4dataEEENS_22__unordered_map_hasherIS8_SB_NS9_8key_hashELb1EEENS_21__unordered_map_equalIS8_SB_NS9_9key_equalELb1EEENS5_ISB_EEE15__insert_uniqueIRKNS_4pairIS8_SA_EEEENSL_INS_15__hash_iteratorIPNS_11__hash_nodeISB_PvEEEEbEEOT_) for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Proces
The main.cpp file
#include "TupleFruits.hpp"
int main()
{
map_t fruitHash = InitializeFruitHash();
std::string fruit = "BANANA";
auto itr = fruitHash(fruit);
if (fruitHash.end() == itr)
{
std::cout << fruit << " not found in hash" << std::endl;
exit(1);
}
}
The FruitHash.cpp file:
#include "TupleFruits.hpp"
map_t InitializeFruitHash()
{
static map_t m;
data dBANANA = {0, 0, 6, false};
data dGRAPEFRUIT = {1, 1, 6, false};
data dSTRAWBERRY = {2, 2, 6, false};
m[BANANA] = dBANANA;
m[GRAPEFRUIT] = dGRAPEFRUIT;
m[STRAWBERRY] = dSTRAWBERRY;
return m;
}
The include file "HashData.hpp
#ifndef HASH_DATA_HPP
#define HASH_DATA_HPP
#include <string>
#include <unordered_map>
#include <cstring>
#include <iostream>
#include <tuple>
#include <boost/functional/hash.hpp>
typedef std::string fruit_key_t;
namespace HASH_TUPLES
{
struct key_hash : public std::unary_function<fruit_key_t, std::size_t>
{
std::size_t operator()(const fruit_key_t& k) const
{
std::hash<std::string> hash_fn;
return hash_fn(k);
}
};
struct key_equal : public std::binary_function<fruit_key_t, fruit_key_t, bool>
{
bool operator()(const fruit_key_t& v0, const fruit_key_t& v1) const
{
return (v0 == v1);
}
};
struct data
{
int row;
int column;
int precision;
bool isRipe;
inline bool operator ==(data d)
{
if (d.row == row && d.column == column)
return true;
else
return false;
}
friend std::ostream& operator << (std::ostream& os, const data& rhs) //Overloaded operator for '<<'
{ //for struct output
os << rhs.row << ", "
<< rhs.column;
return os;
}
};
typedef std::unordered_map<const fruit_key_t, data, key_hash, key_equal> map_t;
// ^ this is our custom hash
}
template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type,
typename T::mapped_type,
bool>
{
public:
bool operator() (typename T::value_type &pair,
typename T::mapped_type i) const
{
return pair.second == i;
}
};
#endif
The include file "TupleFruits.hpp"
#ifndef TUPLESFRUITS_HPP
#define TUPLESFRUITS_HPP
#include <boost/interprocess/containers/string.hpp>
#include "HashData.hpp"
using namespace HASH_TUPLES;
map_t InitializeFruitHash();
static std::string BANANA = "banana";
static std::string GRAPEFRUIT = "grapefruit";
static std::string STRAWBERRY = "strawberry";
#endif
I figured it out. Somehow -s (strip all symbols from binary) snuck in my Makefile
Can someone give me proc_create() example?
Earlier they used create_proc_entry() in the kernel but now they are using proc_create().
This example will create a proc entry which enables reading access. I think you can enable other kinds of access by changing the mode argument passed to the function. I haven't passed a parent directory because there is no need to. The structure file_operations is where you setup your reading and writing callbacks.
struct proc_dir_entry *proc_file_entry;
static const struct file_operations proc_file_fops = {
.owner = THIS_MODULE,
.open = open_callback,
.read = read_callback,
};
int __init init_module(void){
proc_file_entry = proc_create("proc_file_name", 0, NULL, &proc_file_fops);
if(proc_file_entry == NULL)
return -ENOMEM;
return 0;
}
You can check this example for more details: https://www.linux.com/learn/linux-training/37985-the-kernel-newbie-corner-kernel-debugging-using-proc-qsequenceq-files-part-1
Here is a 'hello_proc' code, which makes use of the newer 'proc_create()' interface.
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct file_operations hello_proc_fops = {
.owner = THIS_MODULE,
.open = hello_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
This code has been taken from http://pointer-overloading.blogspot.com/2013/09/linux-creating-entry-in-proc-file.html
This reply is just an update to #Alhaad Gokhale's great answer. The hello world module, as of kernels > 5.6 looks like this:
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct proc_ops hello_proc_fops = {
.proc_open = hello_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
static int __init hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
return 0;
}
static void __exit hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
Key differences to note are:
struct proc_ops replaces struct file_operations.
member name changes from .open, .read to .proc_open, .proc_read...
Need to remove the .owner line.
Further information:
This patch
This more detailed SO answer on changes.