簡體   English   中英

Linux 驅動程序編程:usb_control_msg 問題

[英]Linux Driver Programming: Problem with usb_control_msg

精簡版

我想為自定義 USB 設備編寫 Linux 驅動程序。 在編寫驅動程序之前,我使用 libusb-1.0 來測試設備。 通過以下 function 調用,我可以從設備中讀出 uin16_t 值:

status = libusb_control_transfer(handle,        /* Device Handle */
                                0x80,                           /* bRequestType */
                                0x10,                           /* bRequest */
                                value,                          /* wValue */
                                0x0,                            /* wIndex */
                                ((uint8_t *) &value),           /* data */
                                2,                              /* wLength */
                                100);                           /* timeout */

在這個調用之后,我在 value 變量中得到了一個新值。

現在我想在我的驅動程序中完成相同的調用。 我在 USB 驅動程序的探針 function 中嘗試了以下操作:

status = usb_control_msg(data->udev, usb_rcvctrlpipe(data->udev, 0), 0x10, USB_DIR_IN, 0, 0, (u8*) &my_data, 2, 100);

我得到的只是返回值 -11,在我的設備上我什么也看不到。

在此調用之前我唯一要做的就是調用data->udev = interface_to_usbdev(intf); 從我的界面獲取 USB 設備。

有誰知道,如果我錯過了什么或者我做錯了什么?

長版

我想學習如何在 Linux 中編寫 USB 驅動程序。 作為我可以為其編寫驅動程序的 DUT,我選擇了 Raspberry Pi Pico 和dev_lowlevel USB 示例 我稍微修改了代碼,所以我可以使用 bRequest 0x10 和 bRequestType 0x0 (USB_DIR_OUT) 的控制傳輸來打開或關閉 Pico 的板載 LED,並使用 bRequest 0x10 和 bRequestType 0x80 (USB_DIR_IN) 的控制傳輸來回讀LED 的電流值。

使用用戶空間程序和以下代碼,我可以讀出 LED 的值並將其打開或關閉:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <libusb-1.0/libusb.h>

#define VID 0x0000
#define DID 0x0001

int main(int argc, char **argv) {
        int status, len;
        libusb_device_handle *handle = NULL;

       /* Init Libusb */
        status = libusb_init(NULL);
        if(status < 0) {
                printf("Error init USB!\n");
                return status;
        }

        handle = libusb_open_device_with_vid_pid(NULL, VID, DID);

        if(!handle) {
                printf("No device found with %04x:%04x\n", VID, DID);
                libusb_exit(NULL);
                return -1;
        }
        if(argc > 1)
                value = atoi(argv[1]);
        else {
                /* Do control transfer */
                status = libusb_control_transfer(handle,        /* Device Handle */
                                0x80,                           /* bRequestType */
                                0x10,                           /* bRequest */
                                value,                          /* wValue */
                                0x0,                            /* wIndex */
                                ((uint8_t *) &value),           /* data */
                                2,                              /* wLength */
                                100);                           /* timeout */
                if(status < 0) {
                        printf("Error during control transfer!\n");
                        libusb_close(handle);
                        libusb_exit(NULL);
                        return -1;
                }
                printf("Got: %d\n", value);
                value = (value + 1) & 0x1;
        }

        /* Do control transfer */
        status = libusb_control_transfer(handle, 0x0, 0x10, value, 0x0, NULL, 0, 100);
        if(status < 0) {
                printf("Error during control transfer!\n");
                libusb_close(handle);
                libusb_exit(NULL);
                return -1;
        }
        libusb_close(handle);
        libusb_exit(NULL);

        return 0;
}

現在我想通過 USB 驅動程序控制我的設備。 這是我已經得到的:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/slab.h>

/* Meta Information */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes 4 GNU/Linux");
MODULE_DESCRIPTION("Driver for my custom RPi Pico USB device");

struct pico_usb {
        struct usb_device *udev;
};

#define PICO_VID 0x0000
#define PICO_PID 0x0001

static struct usb_device_id pico_usb_table [] = {
        { USB_DEVICE(PICO_VID, PICO_PID) },
        {},
};
MODULE_DEVICE_TABLE(usb, pico_usb_table);

static int pico_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) {
        struct pico_usb *data;
        int status;
        int my_data;

        printk("pico_usb_drv - Now I am in the Probe function!\n");

        data = kzalloc(sizeof(struct pico_usb), GFP_KERNEL);
        if(!data) {
                printk("pico_usb_drv - Out of memory\n");
                return -ENOMEM;
        }
        data->udev = interface_to_usbdev(intf);
        usb_set_intfdata(intf, data);

        /* Turn the LED on */
        status = usb_control_msg(data->udev, usb_sndctrlpipe(data->udev, 0), 0x10, USB_DIR_OUT, 1, 0, 0, 0, 100);
        /* Read LED state */
        printk("pico_usb_drv - status USB_DIR_OUT: %d\n", status);
        status = usb_control_msg(data->udev, usb_rcvctrlpipe(data->udev, 0), 0x10, USB_DIR_IN, 0, 0, (u8*) &my_data, 2, 100);
        printk("pico_usb_drv - status USB_DIR_IN: %d\n", status);

        return 0;
}

static void pico_usb_disconnect(struct usb_interface *intf) {
        struct pico_usb *data;

        printk("pico_usb_drv - Now I am in the Disconnect function!\n");

        data = usb_get_intfdata(intf);
        kfree(data);

}

static struct usb_driver pico_usb_driver = {
        //.owner = THIS_MODULE,
        .name = "pico_usb",
        .id_table = pico_usb_table,
        .probe = pico_usb_probe,
        .disconnect = pico_usb_disconnect,
};

/**
 * @brief This function is called, when the module is loaded into the kernel
 */
static int __init pico_usb_init(void) {
        int result;
        printk("pico_usb_drv - Registering the PICO USB device\n");
        result = usb_register(&pico_usb_driver);
        if(result) {
                printk("pico_usb_drv - Error registering the PICO USB device\n");
                return -result;
        }
        return 0;
}

/**
 * @brief This function is called, when the module is removed from the kernel
 */
static void __exit pcio_usb_exit(void) {
        printk("pico_usb_drv - Unregistering the PICO USB device\n");
        usb_deregister(&pico_usb_driver);
}

module_init(pico_usb_init);
module_exit(pcio_usb_exit);

第一條控制消息有效,我的 LED 已打開。 但是第二條控制消息沒有做任何事情,而是給了我錯誤代碼-11。

有誰知道,如果我錯過了什么或者我做錯了什么?

好的,我找到了解決方案。 我現在使用usb_control_msg_recv而不是usb_control_msg ,一切正常。

usb_control_msg_recv需要多一個參數:

int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *driver_data, __u16 size, int timeout, gfp_t memflags)

當我將指針傳遞給變量並且不想動態分配 memory 時,我將 memflags 參數設置為 0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM