Advertisement
Guest User

Linux Kernel Module to Access GPS Device

a guest
Jul 29th, 2014
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.28 KB | None | 0 0
  1. #include <linux/errno.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/mutex.h>
  5. #include <linux/slab.h>
  6. #include <linux/uaccess.h>
  7. #include <linux/usb.h>
  8.  
  9. #define USB_VENDOR_ID 0x1546
  10. #define USB_PRODUCT_ID 0x01a7
  11. #define USB_DRIVER_NAME "ublox"
  12. #define UBLOX_MINOR_BASE 192
  13.  
  14. #define PRINT_FIELD(structure, field)                                    \
  15.     do {                                                             \
  16.         printk(KERN_INFO "%s = %u\n", #field, structure->field);  \
  17.     } while (0)
  18. #define get_parent_ublox_device(kref_variable) container_of(kref_variable, struct ublox_device, kref)
  19.  
  20. static int usb_probe(struct usb_interface *interface, const struct usb_device_id *usb_device_id);
  21. static void usb_disconnect(struct usb_interface *interface);
  22. static void usb_print_interface_description(struct usb_interface_descriptor *interface_descriptor);
  23. static int ublox_open(struct inode *inode, struct file *file);
  24. static int ublox_release(struct inode *inode, struct file *file);
  25. static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos);
  26. static void ublox_read_bulk_callback(struct urb *urb);
  27. static void ublox_destroy_device(struct kref *kref);
  28. static void print_struct_urb(struct urb *urb);
  29.  
  30. static struct usb_device_id supported_usb_ids [] = {
  31.     { USB_DEVICE(USB_VENDOR_ID, USB_PRODUCT_ID) },
  32.     { } /* Terminating entry */
  33. };
  34. MODULE_DEVICE_TABLE(usb, supported_usb_ids);
  35.  
  36. static struct usb_driver usb_driver = {
  37.     .name = USB_DRIVER_NAME,
  38.     .id_table = supported_usb_ids,
  39.     .probe = usb_probe,
  40.     .disconnect = usb_disconnect
  41. };
  42.  
  43. static const struct file_operations ublox_fops = {
  44.     .owner = THIS_MODULE,
  45.     .open = ublox_open,
  46.     .release = ublox_release,
  47.     .read = ublox_read
  48. };
  49.  
  50. static struct usb_class_driver ublox_class = {
  51.     .name = USB_DRIVER_NAME,
  52.     .fops = &ublox_fops,
  53.     .minor_base = UBLOX_MINOR_BASE
  54. };
  55.  
  56. struct ublox_device {
  57.     struct usb_device   *usb_device;            /* The usb device to which the ublox device belongs */
  58.     struct usb_interface    *interface;         /* The interface for the ublox device */
  59.     __u8            bulk_in_bEndpointAddress;   /* Address for reading data from ublox device */
  60.     size_t          bulk_in_buffer_size;        /* Size of the input buffer */
  61.     struct urb      *bulk_in_urb;           /* URB for reading data */
  62.     unsigned char       *bulk_in_buffer;        /* Buffer to receive data */
  63.     struct mutex        bulk_in_mutex;          /* Allow only one bulk read operation at a time */
  64.     wait_queue_head_t   bulk_in_wait_queue;     /* Allow only one reader and send all others to sleep */
  65.     bool            read_in_progress;       /* Signal a pending read operation */
  66.     unsigned int        transferred_bytes;      /* The transferred bytes during the last read operation */
  67.     __u8            bulk_out_bEndpointAddress;  /* Address for writing data to ublox device */
  68.     size_t          bulk_out_buffer_size;       /* Size of the output buffer */
  69.     struct kref     kref;               /* Reference counter */
  70. };
  71.  
  72. int init_module(void)
  73. {
  74.     int result;
  75.  
  76.     printk(KERN_INFO "Initializing %s...\n", USB_DRIVER_NAME);
  77.  
  78.     result = usb_register(&usb_driver);
  79.     if (result)
  80.         printk(KERN_INFO "Registering %s failed (result = %d)!\n", USB_DRIVER_NAME, result);
  81.     else
  82.         printk(KERN_INFO "Initialized %s.\n", USB_DRIVER_NAME);
  83.  
  84.     return 0;
  85. }
  86.  
  87. void cleanup_module(void)
  88. {
  89.     usb_deregister(&usb_driver);
  90.  
  91.     printk(KERN_INFO "Cleaned up %s.\n", USB_DRIVER_NAME);
  92. }
  93.  
  94. static int usb_probe(struct usb_interface *interface, const struct usb_device_id *usb_device_id)
  95. {
  96.     struct usb_host_interface *current_interface = interface->cur_altsetting;
  97.     struct ublox_device *ublox_device = NULL;
  98.     int in_endpoint_found = 0;
  99.     int out_endpoint_found = 0;
  100.     int return_value = -EINVAL;
  101.     int i;
  102.  
  103.     printk(KERN_INFO "Probing USB interface...\n");
  104.  
  105.     /* Accept only interfaces with two endpoints (one for reading, one for writing) */
  106.     if (current_interface->desc.bNumEndpoints != 2) {
  107.         printk(KERN_INFO "Ignoring USB interface %d!\n", current_interface->desc.bInterfaceNumber);
  108.         usb_print_interface_description(&current_interface->desc);
  109.     } else {
  110.         ublox_device = kzalloc(sizeof(*ublox_device), GFP_KERNEL);
  111.         if (ublox_device == NULL) {
  112.             return_value = -ENOMEM;
  113.             goto error;
  114.         }
  115.  
  116.         ublox_device->usb_device = usb_get_dev(interface_to_usbdev(interface));
  117.         ublox_device->interface = interface;
  118.         ublox_device->read_in_progress = 0;
  119.         ublox_device->transferred_bytes = 0;
  120.  
  121.         mutex_init(&ublox_device->bulk_in_mutex);
  122.         init_waitqueue_head(&ublox_device->bulk_in_wait_queue);
  123.         kref_init(&ublox_device->kref);
  124.  
  125.         ublox_device->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
  126.         if (ublox_device->bulk_in_urb == NULL) {
  127.             return_value = -ENOMEM;
  128.             goto error;
  129.         }
  130.  
  131.         for (i = 0; i < current_interface->desc.bNumEndpoints; i++) {
  132.             struct usb_endpoint_descriptor endpoint = current_interface->endpoint[i].desc;
  133.  
  134.             if (usb_endpoint_is_bulk_in(&endpoint)) {
  135.                 ublox_device->bulk_in_bEndpointAddress = endpoint.bEndpointAddress;
  136.                 ublox_device->bulk_in_buffer_size = endpoint.wMaxPacketSize;
  137.  
  138.                 ublox_device->bulk_in_buffer = kzalloc(endpoint.wMaxPacketSize, GFP_KERNEL);
  139.                 if (ublox_device->bulk_in_buffer == NULL) {
  140.                     return_value = -ENOMEM;
  141.                     goto error;
  142.                 }
  143.  
  144.                 in_endpoint_found = 1;
  145.             }
  146.  
  147.             if (usb_endpoint_is_bulk_out(&endpoint)) {
  148.                 ublox_device->bulk_out_bEndpointAddress = endpoint.bEndpointAddress;
  149.                 ublox_device->bulk_out_buffer_size = endpoint.wMaxPacketSize;
  150.  
  151.                 out_endpoint_found = 1;
  152.             }
  153.         }
  154.  
  155.         if (in_endpoint_found && out_endpoint_found) {
  156.             printk(KERN_INFO "Handling USB interface %d.\n", current_interface->desc.bInterfaceNumber);
  157.             usb_print_interface_description(&current_interface->desc);
  158.  
  159.             return_value = usb_register_dev(interface, &ublox_class);
  160.             if (return_value) {
  161.                 printk(KERN_ERR "Unable to register USB interface %d!\n", current_interface->desc.bInterfaceNumber);
  162.                 goto error;
  163.             }
  164.  
  165.             usb_set_intfdata(interface, ublox_device);
  166.         }
  167.         else
  168.             goto error;
  169.     }
  170.  
  171.     printk(KERN_INFO "Probed USB interface.\n");
  172.  
  173.     return return_value;
  174.  
  175. error:
  176.     if (ublox_device)
  177.         kref_put(&ublox_device->kref, ublox_destroy_device);
  178.  
  179.     return return_value;
  180. }
  181.  
  182. static void usb_disconnect(struct usb_interface *interface)
  183. {
  184.     struct ublox_device *ublox_device = usb_get_intfdata(interface);
  185.     int minor = interface->minor;
  186.  
  187.     /* Wait for pending I/O operations and then prevent more I/O operations from starting */
  188.     mutex_lock(&ublox_device->bulk_in_mutex);
  189.  
  190.     usb_set_intfdata(interface, NULL);
  191.     usb_deregister_dev(interface, &ublox_class);
  192.     kref_put(&ublox_device->kref, ublox_destroy_device);
  193.  
  194.     mutex_unlock(&ublox_device->bulk_in_mutex);
  195.  
  196.     printk(KERN_INFO "Disconnected USB interface with minor number %d.\n", minor);
  197. }
  198.  
  199. static void usb_print_interface_description(struct usb_interface_descriptor *interface_descriptor)
  200. {
  201.     printk(KERN_INFO "Printing interface description...\n");
  202.  
  203.     PRINT_FIELD(interface_descriptor, bInterfaceNumber);
  204.     PRINT_FIELD(interface_descriptor, bNumEndpoints);
  205.     PRINT_FIELD(interface_descriptor, bInterfaceClass);
  206.     PRINT_FIELD(interface_descriptor, bInterfaceSubClass);
  207.  
  208.     printk(KERN_INFO "Printed interface description.\n");
  209. }
  210.  
  211. static int ublox_open(struct inode *inode, struct file *file)
  212. {
  213.     struct ublox_device *ublox_device;
  214.     struct usb_interface *interface;
  215.     int minor;
  216.     int return_value = 0;
  217.  
  218.     printk(KERN_INFO "Opening ublox device...\n");
  219.  
  220.     minor = iminor(inode);
  221.  
  222.     interface = usb_find_interface(&usb_driver, minor);
  223.     if (!interface) {
  224.         printk(KERN_ERR "Cannot find USB device for minor number %d!\n", minor);
  225.         return_value = -ENODEV;
  226.         goto exit;
  227.     }
  228.  
  229.     ublox_device = usb_get_intfdata(interface);
  230.     if (!ublox_device) {
  231.         printk(KERN_ERR "Cannot find ublox_device data in interface!\n");
  232.         return_value = -ENODEV;
  233.         goto exit;
  234.     }
  235.  
  236.     kref_get(&ublox_device->kref);
  237.     file->private_data = ublox_device;
  238.  
  239.     printk(KERN_INFO "Opened ublox device.\n");
  240. exit:
  241.     return return_value;
  242. }
  243.  
  244. static int ublox_release(struct inode *inode, struct file *file)
  245. {
  246.     struct ublox_device *ublox_device = file->private_data;
  247.  
  248.     printk(KERN_INFO "Releasing ublox device...\n");
  249.  
  250.     if (ublox_device == NULL)
  251.         return -ENODEV;
  252.  
  253.     kref_put(&ublox_device->kref, ublox_destroy_device);
  254.  
  255.     printk(KERN_INFO "Released ublox device.\n");
  256.  
  257.     return 0;
  258. }
  259.  
  260. static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
  261. {
  262.     struct ublox_device *ublox_device = file->private_data;
  263.     int bytes_to_read = 0;
  264.     int return_value = 0;
  265.  
  266.     if (ublox_device == NULL)
  267.         return -ENODEV;
  268.  
  269.     bytes_to_read = min(count, ublox_device->bulk_in_buffer_size);
  270.  
  271.     return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
  272.     if (return_value < 0)
  273.         return -EINTR;
  274.  
  275.     printk(KERN_INFO "Reading ublox device...\n");
  276.     printk(KERN_INFO "count = %d\n", count);
  277.     printk(KERN_INFO "pos = %lu\n", (unsigned long)*pos);
  278.     printk(KERN_INFO "pid = %d\n", current->pid);
  279.  
  280.     if (ublox_device->interface == NULL) { /* disconnect(...) was called in the meantime */
  281.         return_value = -ENODEV;
  282.         goto exit;
  283.     }
  284.  
  285. retry:
  286.     usb_fill_bulk_urb(ublox_device->bulk_in_urb,
  287.             ublox_device->usb_device,
  288.             usb_rcvbulkpipe(ublox_device->usb_device, ublox_device->bulk_in_bEndpointAddress),
  289.             ublox_device->bulk_in_buffer,
  290.             bytes_to_read,
  291.             ublox_read_bulk_callback,
  292.             ublox_device);
  293.  
  294.     ublox_device->read_in_progress = 1;
  295.  
  296.     return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
  297.     if (return_value) {
  298.         printk(KERN_ERR "usb_submit_urb(...) failed!\n");
  299.         ublox_device->read_in_progress = 0;
  300.         goto exit;
  301.     }
  302.  
  303.     /* Go to sleep until read operation has finished */
  304.     return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
  305.     if (return_value < 0)
  306.         goto exit;
  307.  
  308.     if (ublox_device->transferred_bytes > bytes_to_read) {
  309.         return_value = -EIO;
  310.         goto exit;
  311.     } else if (ublox_device->transferred_bytes == 0) {
  312.         goto retry;
  313.     }
  314.  
  315.     if (copy_to_user(buffer, ublox_device->bulk_in_buffer, ublox_device->transferred_bytes)) {
  316.         return_value = -EFAULT;
  317.         goto exit;
  318.     } else {
  319.         return_value = ublox_device->transferred_bytes;
  320.     }
  321.  
  322.  
  323. exit:
  324.     print_struct_urb(ublox_device->bulk_in_urb);
  325.  
  326.     printk(KERN_INFO "bytes_to_read = %d\n", bytes_to_read);
  327.     printk(KERN_INFO "transferred_bytes = %d\n", ublox_device->transferred_bytes);
  328.     printk(KERN_INFO "Read ublox device.\n");
  329.  
  330.     mutex_unlock(&ublox_device->bulk_in_mutex);
  331.     return return_value;
  332. }
  333.  
  334. static void ublox_read_bulk_callback(struct urb *urb)
  335. {
  336.     struct ublox_device *ublox_device = urb->context;
  337.     int status = urb->status;
  338.  
  339.     if (status) {
  340.         if (status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)
  341.             printk(KERN_WARNING "Sync/Async/Unlink I/O error: %d\n", status);
  342.         else
  343.             printk(KERN_ERR "Critical I/O error: %d\n", status);
  344.     }
  345.  
  346.     ublox_device->transferred_bytes = urb->actual_length;
  347.     ublox_device->read_in_progress = 0;
  348.  
  349.     wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
  350. }
  351.  
  352. static void ublox_destroy_device(struct kref *kref)
  353. {
  354.     struct ublox_device *ublox_device = get_parent_ublox_device(kref);
  355.  
  356.     usb_free_urb(ublox_device->bulk_in_urb);
  357.     kfree(ublox_device->bulk_in_buffer);
  358.     kfree(ublox_device);
  359. }
  360.  
  361. static void print_struct_urb(struct urb *urb)
  362. {
  363.     PRINT_FIELD(urb, unlinked);
  364.     PRINT_FIELD(urb, status);
  365.     PRINT_FIELD(urb, num_sgs);
  366.     PRINT_FIELD(urb, transfer_buffer_length);
  367.     PRINT_FIELD(urb, actual_length);
  368. }
  369.  
  370. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement