Jared Hart Jared Hart - 29 days ago 12
C Question

C Linux USB Driver | Best way to print URB buffer contents

I'm new to Linux USB driver development, and I absolutely love it so far! I'm currently creating a driver for an Xbox One controller, and I have a question for you guys. In the below code, you will see that I fill an interrupt IN URB in the open function, and I would like to print the contents of the URB buffer in the xb1_int_in_callback() function. What would be the best way to do this? At the moment, I'm using printk(KERN_INFO "int_in_buffer: %s", dev->int_in_buffer), however I don't see the entire URB buffer contents printed, and get a weird string printed to dmesg.

Sorry if this is a simple question, I'm new to programming and C, so I'm still learning as I go, but I absolutely love it so far!

Code:

static void xb1_int_in_callback(struct urb *int_in_urb) {
struct xb1_controller *dev = int_in_urb->context;

printk(KERN_INFO "xb1_int_in_callback successfully called");
printk(KERN_INFO "int_in_buffer: %s", dev->int_in_buffer);
}

static int xb1_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "open function called..");

struct xb1_controller *dev;
struct usb_interface *interface;
int subminor;
int retval = 0;

subminor = iminor(inode);

interface = usb_find_interface(&xb1_driver, subminor);
if(!interface) {
printk(KERN_INFO "Unable to locate interface in open
function");
retval = -ENODEV;
goto exit;
}

dev = usb_get_intfdata(interface);
if(!dev) {
printk(KERN_INFO "Unable to locate dev structure in open
function");
retval = -ENODEV;
goto exit;
}

usb_fill_int_urb(dev->int_in_urb, dev->udev, usb_rcvintpipe(dev-
>udev, dev->int_in_endpoint->bEndpointAddress),
dev->int_in_buffer, dev->int_in_endpoint-
>wMaxPacketSize, xb1_int_in_callback,
dev, dev->int_in_endpoint->bInterval);

dev->int_in_running = 1;

retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL);
if(retval) {
printk(KERN_INFO "Unable to submit int_in_urb in open
function");
dev->int_in_running = 0;
goto exit;
}

file->private_data = dev;

exit:
return retval;
}


static int xb1_probe(struct usb_interface *interface, const struct
usb_device_id *id) {
struct usb_device *udev = interface_to_usbdev(interface);
struct xb1_controller *dev = NULL;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i;
int retval = -ENODEV;

if(!udev) {
printk(KERN_INFO "udev is NULL in probe function");
xb1_abort(dev);
return retval;
}

dev = kzalloc(sizeof(struct xb1_controller), GFP_KERNEL);
if(!dev) {
printk(KERN_INFO "Unable to allocate memory for dev in probe
function");
xb1_abort(dev);
return retval;
}

dev->udev = udev;
dev->interface = interface;

iface_desc = interface->cur_altsetting;

for(i=0; i<iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;

if(((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
USB_DIR_IN)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT)) {

dev->int_in_endpoint = endpoint;
}
}

if(!dev->int_in_endpoint) {
printk(KERN_INFO "Unable to locate interrupt in endpoint for
interface in probe function");
xb1_abort(dev);
return retval;
}
else {
printk(KERN_INFO "Interrupt in endpoint found!");
}

Answer

For printing a small buffers (up to 64 bytes long) use printk format:

Raw buffer as a hex string:

%*ph    00 01 02  ...  3f
%*phC   00:01:02: ... :3f
%*phD   00-01-02- ... -3f
%*phN   000102 ... 3f

For larger buffers use print_hex_dump(). Reference here.

Comments