hsync hsync - 1 month ago 13
C Question

Bulk message transfer USB Linux

I am at the very beginning to write my own Linux Driver for a dds generator.

I want to write 2 bulk messgages to the generator when der Kernel call the probe function. But I dont know how to call the usb_bulk_msg function. I hope you could me.

hsync

static int dds_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
int retval = 0;

retval = usb_bulk_msg();

dev_info(&interface->dev, "DDS generator is now attached\n");
return 0;
}

Answer

Kernel is kinda self-explanatory project, so usually you can find an answer right in kernel code.

Function usage

include/linux/usb.h: here you can see signature of this function

extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
                        void *data, int len, int *actual_length,
                        int timeout);

drivers/usb/core/message.c: here you can see nice description for this function (parameters, return value, how to use it)

/**
 * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
 * @usb_dev: pointer to the usb device to send the message to
 * @pipe: endpoint "pipe" to send the message to
 * @data: pointer to the data to send
 * @len: length in bytes of the data to send
 * @actual_length: pointer to a location to put the actual length transferred
 *                 in bytes
 * @timeout: time in msecs to wait for the message to complete before
 *           timing out (if 0 the wait is forever)
 *
 * Context: !in_interrupt ()
 *
 * This function sends a simple bulk message to a specified endpoint
 * and waits for the message to complete, or timeout.
 *
 * Don't use this function from within an interrupt context, like a bottom half
 * handler.  If you need an asynchronous message, or need to send a message
 * from within interrupt context, use usb_submit_urb() If a thread in your
 * driver uses this call, make sure your disconnect() method can wait for it to
 * complete.  Since you don't have a handle on the URB used, you can't cancel
 * the request.
 *
 * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
 * users are forced to abuse this routine by using it to submit URBs for
 * interrupt endpoints.  We will take the liberty of creating an interrupt URB
 * (with the default interval) if the target is an interrupt endpoint.
 *
 * Return:
 * If successful, 0. Otherwise a negative error number. The number of actual
 * bytes transferred will be stored in the @actual_length parameter.
 *
 */

Examples

If you need some examples how to use this function, you can also find them in kernel code, e.g. using LXR site.

If you are novice to USB drivers development, you may also be interested in some tutorials:

Answering question in comments

when I plug in my generator, the kernel execute my driver but then the usbcore loads the usbhid driver, because the generator is an hid device and at the next time the usbcore does not execute my "driver".

I know two possible ways to fix that:

  1. Using usbhid driver's "quirks" param.

    Provide your device's Vendor ID and Product ID as quirks param to usbhid module. You can pass this param via kernel cmdline. Edit /etc/default/grub file, adding something like usbhid.quirks=0xdead:0xbeef:0x4 to GRUB_CMDLINE_LINUX_DEFAULT, and then do:

    $ sudo update-grub
    

    Then reboot.

  2. Using udev.

    Create udev rule for your device with ignore_device option. But it seems like this option was removed in new versions of udev, so you may be unable to use it.

Details:

[1] http://unix.stackexchange.com/questions/55495/prevent-usbhid-from-claiming-usb-device/55590#55590

[2] http://ubuntuforums.org/showthread.php?t=1175001&p=7548820#post7548820