Linux USB-драйвер: usb_find_interface возвращает NULL - PullRequest
0 голосов
/ 12 апреля 2020

В настоящее время я пишу Linux USB-драйвер для микрофона, и я ориентируюсь на этот драйвер скелета: https://elixir.bootlin.com/linux/latest/source/drivers/usb/usb-skeleton.c

Для целей тестирования он настроен как символьный драйвер, так что я могу заполнить буфер в функции чтения вручную и прочитать его в приложении пространства пользователя. К сожалению, вызов

interface = usb_find_interface(&mic_driver, subminor);

в моей открытой функции приводит к NULL Pointer для интерфейса. Таким образом, интерфейс не найден. Я дважды проверил идентификаторы поставщиков и продуктов для моего микрофона с помощью «lsusb». Я был бы рад, если бы кто-нибудь мог указать мне на то, что мне не хватает.


#include <linux/kernel.h>
#include <linux/slab.h>     // kmalloc
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/fs.h>       // File S
#include <asm/uaccess.h>    //copy_to_user

#include <linux/init.h>
#include <linux/cdev.h>

#define USB_VENDOR_ID   0x8086
#define USB_PRODUCT_ID  0x0808

static char *mes = "Driver works as intended";
static char *mp;

static const struct usb_device_id mic_table[] = {
    { USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
    { }                                         
};
MODULE_DEVICE_TABLE (usb, mic_table);       //usb is just a type

struct usb_all {
    struct usb_device       *udev;          //device
    struct usb_interface    *interface;     //neccessary interface
    struct urb                  *in_urb;
};

static struct tty_struct *my_tty;
static int use_count;
static struct usb_driver mic_driver;
static char device_name[] = "MicDriver";

int device_open         (struct inode *inode, struct file *file) {

    struct usb_all *dev;
    struct usb_interface *interface;
    int subminor;

    subminor = iminor(inode);
    mp = mes; // For character test

    printk(KERN_INFO "Subminor: %i \n", subminor);
    printk(KERN_INFO "Address: %i \n", &mic_driver);
    if (&mic_driver == NULL) { printk(KERN_INFO "Mic Driver NULL"); }
    interface = usb_find_interface(&mic_driver, subminor);
    if (interface == NULL) { 
        printk(KERN_INFO "No interface found in open function\n"); 
        goto exit;
    }
    dev = usb_get_intfdata(interface);
    file->private_data = dev;

exit:
    return 0;
};

static int mic_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
    printk(KERN_INFO "USB Microphone connected \n");
    struct usb_all *dev;
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);

    if (interface == NULL) {
        printk(KERN_INFO "No interface in probe function \n");
        goto exit;
    }
    if(dev == NULL) {
        printk(KERN_INFO "No struct usb_all in probe function \n");
        goto exit;
    }
    dev->udev = usb_get_dev(interface_to_usbdev(interface));    //usb_dev from interface
    dev->interface = usb_get_intf(interface);
    usb_set_intfdata(interface, dev);                           // link to open
exit:
    return 0;
};

static void mic_disconnect(struct usb_interface *interface) {
    printk(KERN_INFO "USB Microphone disconnected \n");
};

//read, open, release // ssize_t ist signed size of allocated memory
ssize_t device_read (struct file *file, char *buffer, size_t len, loff_t *offs) {
    struct urb *urb1;
    struct usb_all *dev;
    int reval = 0;
    /*
    dev = file->private_data;
    urb1 = usb_alloc_urb(1, GFP_KERNEL); //Isopackages, mem_flag
    if (urb1 == NULL) {
        return -EAGAIN;
    };
    */

    reval = copy_to_user(buffer, mp, 16);
    mp += 16;
    return reval;
}; 

void device_release     (struct inode *inode, struct file *file) {
    struct usb_all *dev;
    dev = file->private_data;
    if (dev != NULL) {
    usb_put_intf(dev->interface);
    usb_put_dev(dev->udev);
    kfree(dev);
    }
};

int completion_handler(struct urb *urb) {
    if (urb != NULL) {
    usb_free_coherent(urb->dev, urb->transfer_buffer_length,urb->transfer_buffer, urb->transfer_dma);
    usb_free_urb(urb);
    }
    return 0;
};

static struct file_operations fops = {   
    read:       device_read,
    open:       device_open,
    release:    device_release,
    owner:      THIS_MODULE
};  

static struct usb_driver mic_driver = 
{
    .name           = "MicDriver",
    .id_table       = mic_table,        // Type usb_device_id
    .probe          = mic_probe,
    .disconnect     = mic_disconnect,
};

static          dev_t   dev2;           // Major und minor
static struct   cdev    *my_cdev;       // Character device

int mic_init(void) {
    int ret = 0;
    char message[64];

    ret = alloc_chrdev_region(&dev2, 0, 1, device_name);
    if (ret < 0 ) { return -1;}
    my_cdev = cdev_alloc();
    my_cdev->ops = &fops;
    my_cdev->owner = THIS_MODULE;
    ret = cdev_add(my_cdev, dev2, 1);
    if (ret < 0 ) { 
        unregister_chrdev_region(dev2, 1);
        return -1;
    }

    ret = usb_register(&mic_driver);
    my_tty = get_current_tty();
    if (my_tty == NULL) return -ENOTTY;

    sprintf(message, "USB Driver created \r\n");
    (my_tty->ops->write)
                            (my_tty, message, strlen(message));
    printk(KERN_INFO "Init okay");
    return ret;
}

void mic_exit(void) {
    char message[64];
    usb_deregister(&mic_driver);
    sprintf(message, "USB Driver removed \r\n");
    (my_tty->ops->write)
                            (my_tty, message, strlen(message));

    cdev_del(my_cdev);
    unregister_chrdev_region(dev2, 1);
}
MODULE_LICENSE("GPL v2");

module_init(mic_init);
module_exit(mic_exit);
...