usb.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Generic USB GNSS receiver driver
  4. *
  5. * Copyright (C) 2021 Johan Hovold <[email protected]>
  6. */
  7. #include <linux/errno.h>
  8. #include <linux/gnss.h>
  9. #include <linux/init.h>
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <linux/slab.h>
  13. #include <linux/usb.h>
  14. #define GNSS_USB_READ_BUF_LEN 512
  15. #define GNSS_USB_WRITE_TIMEOUT 1000
  16. static const struct usb_device_id gnss_usb_id_table[] = {
  17. { USB_DEVICE(0x1199, 0xb000) }, /* Sierra Wireless XM1210 */
  18. { }
  19. };
  20. MODULE_DEVICE_TABLE(usb, gnss_usb_id_table);
  21. struct gnss_usb {
  22. struct usb_device *udev;
  23. struct usb_interface *intf;
  24. struct gnss_device *gdev;
  25. struct urb *read_urb;
  26. unsigned int write_pipe;
  27. };
  28. static void gnss_usb_rx_complete(struct urb *urb)
  29. {
  30. struct gnss_usb *gusb = urb->context;
  31. struct gnss_device *gdev = gusb->gdev;
  32. int status = urb->status;
  33. int len;
  34. int ret;
  35. switch (status) {
  36. case 0:
  37. break;
  38. case -ENOENT:
  39. case -ECONNRESET:
  40. case -ESHUTDOWN:
  41. dev_dbg(&gdev->dev, "urb stopped: %d\n", status);
  42. return;
  43. case -EPIPE:
  44. dev_err(&gdev->dev, "urb stopped: %d\n", status);
  45. return;
  46. default:
  47. dev_dbg(&gdev->dev, "nonzero urb status: %d\n", status);
  48. goto resubmit;
  49. }
  50. len = urb->actual_length;
  51. if (len == 0)
  52. goto resubmit;
  53. ret = gnss_insert_raw(gdev, urb->transfer_buffer, len);
  54. if (ret < len)
  55. dev_dbg(&gdev->dev, "dropped %d bytes\n", len - ret);
  56. resubmit:
  57. ret = usb_submit_urb(urb, GFP_ATOMIC);
  58. if (ret && ret != -EPERM && ret != -ENODEV)
  59. dev_err(&gdev->dev, "failed to resubmit urb: %d\n", ret);
  60. }
  61. static int gnss_usb_open(struct gnss_device *gdev)
  62. {
  63. struct gnss_usb *gusb = gnss_get_drvdata(gdev);
  64. int ret;
  65. ret = usb_submit_urb(gusb->read_urb, GFP_KERNEL);
  66. if (ret) {
  67. if (ret != -EPERM && ret != -ENODEV)
  68. dev_err(&gdev->dev, "failed to submit urb: %d\n", ret);
  69. return ret;
  70. }
  71. return 0;
  72. }
  73. static void gnss_usb_close(struct gnss_device *gdev)
  74. {
  75. struct gnss_usb *gusb = gnss_get_drvdata(gdev);
  76. usb_kill_urb(gusb->read_urb);
  77. }
  78. static int gnss_usb_write_raw(struct gnss_device *gdev,
  79. const unsigned char *buf, size_t count)
  80. {
  81. struct gnss_usb *gusb = gnss_get_drvdata(gdev);
  82. void *tbuf;
  83. int ret;
  84. tbuf = kmemdup(buf, count, GFP_KERNEL);
  85. if (!tbuf)
  86. return -ENOMEM;
  87. ret = usb_bulk_msg(gusb->udev, gusb->write_pipe, tbuf, count, NULL,
  88. GNSS_USB_WRITE_TIMEOUT);
  89. kfree(tbuf);
  90. if (ret)
  91. return ret;
  92. return count;
  93. }
  94. static const struct gnss_operations gnss_usb_gnss_ops = {
  95. .open = gnss_usb_open,
  96. .close = gnss_usb_close,
  97. .write_raw = gnss_usb_write_raw,
  98. };
  99. static int gnss_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
  100. {
  101. struct usb_device *udev = interface_to_usbdev(intf);
  102. struct usb_endpoint_descriptor *in, *out;
  103. struct gnss_device *gdev;
  104. struct gnss_usb *gusb;
  105. struct urb *urb;
  106. size_t buf_len;
  107. void *buf;
  108. int ret;
  109. ret = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL,
  110. NULL);
  111. if (ret)
  112. return ret;
  113. gusb = kzalloc(sizeof(*gusb), GFP_KERNEL);
  114. if (!gusb)
  115. return -ENOMEM;
  116. gdev = gnss_allocate_device(&intf->dev);
  117. if (!gdev) {
  118. ret = -ENOMEM;
  119. goto err_free_gusb;
  120. }
  121. gdev->ops = &gnss_usb_gnss_ops;
  122. gdev->type = GNSS_TYPE_NMEA;
  123. gnss_set_drvdata(gdev, gusb);
  124. urb = usb_alloc_urb(0, GFP_KERNEL);
  125. if (!urb) {
  126. ret = -ENOMEM;
  127. goto err_put_gdev;
  128. }
  129. buf_len = max(usb_endpoint_maxp(in), GNSS_USB_READ_BUF_LEN);
  130. buf = kzalloc(buf_len, GFP_KERNEL);
  131. if (!buf) {
  132. ret = -ENOMEM;
  133. goto err_free_urb;
  134. }
  135. usb_fill_bulk_urb(urb, udev,
  136. usb_rcvbulkpipe(udev, usb_endpoint_num(in)),
  137. buf, buf_len, gnss_usb_rx_complete, gusb);
  138. gusb->intf = intf;
  139. gusb->udev = udev;
  140. gusb->gdev = gdev;
  141. gusb->read_urb = urb;
  142. gusb->write_pipe = usb_sndbulkpipe(udev, usb_endpoint_num(out));
  143. ret = gnss_register_device(gdev);
  144. if (ret)
  145. goto err_free_buf;
  146. usb_set_intfdata(intf, gusb);
  147. return 0;
  148. err_free_buf:
  149. kfree(buf);
  150. err_free_urb:
  151. usb_free_urb(urb);
  152. err_put_gdev:
  153. gnss_put_device(gdev);
  154. err_free_gusb:
  155. kfree(gusb);
  156. return ret;
  157. }
  158. static void gnss_usb_disconnect(struct usb_interface *intf)
  159. {
  160. struct gnss_usb *gusb = usb_get_intfdata(intf);
  161. gnss_deregister_device(gusb->gdev);
  162. kfree(gusb->read_urb->transfer_buffer);
  163. usb_free_urb(gusb->read_urb);
  164. gnss_put_device(gusb->gdev);
  165. kfree(gusb);
  166. }
  167. static struct usb_driver gnss_usb_driver = {
  168. .name = "gnss-usb",
  169. .probe = gnss_usb_probe,
  170. .disconnect = gnss_usb_disconnect,
  171. .id_table = gnss_usb_id_table,
  172. };
  173. module_usb_driver(gnss_usb_driver);
  174. MODULE_AUTHOR("Johan Hovold <[email protected]>");
  175. MODULE_DESCRIPTION("Generic USB GNSS receiver driver");
  176. MODULE_LICENSE("GPL v2");