0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/errno.h>
0009 #include <linux/gnss.h>
0010 #include <linux/init.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/slab.h>
0014 #include <linux/usb.h>
0015
0016 #define GNSS_USB_READ_BUF_LEN 512
0017 #define GNSS_USB_WRITE_TIMEOUT 1000
0018
0019 static const struct usb_device_id gnss_usb_id_table[] = {
0020 { USB_DEVICE(0x1199, 0xb000) },
0021 { }
0022 };
0023 MODULE_DEVICE_TABLE(usb, gnss_usb_id_table);
0024
0025 struct gnss_usb {
0026 struct usb_device *udev;
0027 struct usb_interface *intf;
0028 struct gnss_device *gdev;
0029 struct urb *read_urb;
0030 unsigned int write_pipe;
0031 };
0032
0033 static void gnss_usb_rx_complete(struct urb *urb)
0034 {
0035 struct gnss_usb *gusb = urb->context;
0036 struct gnss_device *gdev = gusb->gdev;
0037 int status = urb->status;
0038 int len;
0039 int ret;
0040
0041 switch (status) {
0042 case 0:
0043 break;
0044 case -ENOENT:
0045 case -ECONNRESET:
0046 case -ESHUTDOWN:
0047 dev_dbg(&gdev->dev, "urb stopped: %d\n", status);
0048 return;
0049 case -EPIPE:
0050 dev_err(&gdev->dev, "urb stopped: %d\n", status);
0051 return;
0052 default:
0053 dev_dbg(&gdev->dev, "nonzero urb status: %d\n", status);
0054 goto resubmit;
0055 }
0056
0057 len = urb->actual_length;
0058 if (len == 0)
0059 goto resubmit;
0060
0061 ret = gnss_insert_raw(gdev, urb->transfer_buffer, len);
0062 if (ret < len)
0063 dev_dbg(&gdev->dev, "dropped %d bytes\n", len - ret);
0064 resubmit:
0065 ret = usb_submit_urb(urb, GFP_ATOMIC);
0066 if (ret && ret != -EPERM && ret != -ENODEV)
0067 dev_err(&gdev->dev, "failed to resubmit urb: %d\n", ret);
0068 }
0069
0070 static int gnss_usb_open(struct gnss_device *gdev)
0071 {
0072 struct gnss_usb *gusb = gnss_get_drvdata(gdev);
0073 int ret;
0074
0075 ret = usb_submit_urb(gusb->read_urb, GFP_KERNEL);
0076 if (ret) {
0077 if (ret != -EPERM && ret != -ENODEV)
0078 dev_err(&gdev->dev, "failed to submit urb: %d\n", ret);
0079 return ret;
0080 }
0081
0082 return 0;
0083 }
0084
0085 static void gnss_usb_close(struct gnss_device *gdev)
0086 {
0087 struct gnss_usb *gusb = gnss_get_drvdata(gdev);
0088
0089 usb_kill_urb(gusb->read_urb);
0090 }
0091
0092 static int gnss_usb_write_raw(struct gnss_device *gdev,
0093 const unsigned char *buf, size_t count)
0094 {
0095 struct gnss_usb *gusb = gnss_get_drvdata(gdev);
0096 void *tbuf;
0097 int ret;
0098
0099 tbuf = kmemdup(buf, count, GFP_KERNEL);
0100 if (!tbuf)
0101 return -ENOMEM;
0102
0103 ret = usb_bulk_msg(gusb->udev, gusb->write_pipe, tbuf, count, NULL,
0104 GNSS_USB_WRITE_TIMEOUT);
0105 kfree(tbuf);
0106 if (ret)
0107 return ret;
0108
0109 return count;
0110 }
0111
0112 static const struct gnss_operations gnss_usb_gnss_ops = {
0113 .open = gnss_usb_open,
0114 .close = gnss_usb_close,
0115 .write_raw = gnss_usb_write_raw,
0116 };
0117
0118 static int gnss_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
0119 {
0120 struct usb_device *udev = interface_to_usbdev(intf);
0121 struct usb_endpoint_descriptor *in, *out;
0122 struct gnss_device *gdev;
0123 struct gnss_usb *gusb;
0124 struct urb *urb;
0125 size_t buf_len;
0126 void *buf;
0127 int ret;
0128
0129 ret = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL,
0130 NULL);
0131 if (ret)
0132 return ret;
0133
0134 gusb = kzalloc(sizeof(*gusb), GFP_KERNEL);
0135 if (!gusb)
0136 return -ENOMEM;
0137
0138 gdev = gnss_allocate_device(&intf->dev);
0139 if (!gdev) {
0140 ret = -ENOMEM;
0141 goto err_free_gusb;
0142 }
0143
0144 gdev->ops = &gnss_usb_gnss_ops;
0145 gdev->type = GNSS_TYPE_NMEA;
0146 gnss_set_drvdata(gdev, gusb);
0147
0148 urb = usb_alloc_urb(0, GFP_KERNEL);
0149 if (!urb) {
0150 ret = -ENOMEM;
0151 goto err_put_gdev;
0152 }
0153
0154 buf_len = max(usb_endpoint_maxp(in), GNSS_USB_READ_BUF_LEN);
0155
0156 buf = kzalloc(buf_len, GFP_KERNEL);
0157 if (!buf) {
0158 ret = -ENOMEM;
0159 goto err_free_urb;
0160 }
0161
0162 usb_fill_bulk_urb(urb, udev,
0163 usb_rcvbulkpipe(udev, usb_endpoint_num(in)),
0164 buf, buf_len, gnss_usb_rx_complete, gusb);
0165
0166 gusb->intf = intf;
0167 gusb->udev = udev;
0168 gusb->gdev = gdev;
0169 gusb->read_urb = urb;
0170 gusb->write_pipe = usb_sndbulkpipe(udev, usb_endpoint_num(out));
0171
0172 ret = gnss_register_device(gdev);
0173 if (ret)
0174 goto err_free_buf;
0175
0176 usb_set_intfdata(intf, gusb);
0177
0178 return 0;
0179
0180 err_free_buf:
0181 kfree(buf);
0182 err_free_urb:
0183 usb_free_urb(urb);
0184 err_put_gdev:
0185 gnss_put_device(gdev);
0186 err_free_gusb:
0187 kfree(gusb);
0188
0189 return ret;
0190 }
0191
0192 static void gnss_usb_disconnect(struct usb_interface *intf)
0193 {
0194 struct gnss_usb *gusb = usb_get_intfdata(intf);
0195
0196 gnss_deregister_device(gusb->gdev);
0197
0198 kfree(gusb->read_urb->transfer_buffer);
0199 usb_free_urb(gusb->read_urb);
0200 gnss_put_device(gusb->gdev);
0201 kfree(gusb);
0202 }
0203
0204 static struct usb_driver gnss_usb_driver = {
0205 .name = "gnss-usb",
0206 .probe = gnss_usb_probe,
0207 .disconnect = gnss_usb_disconnect,
0208 .id_table = gnss_usb_id_table,
0209 };
0210 module_usb_driver(gnss_usb_driver);
0211
0212 MODULE_AUTHOR("Johan Hovold <johan@kernel.org>");
0213 MODULE_DESCRIPTION("Generic USB GNSS receiver driver");
0214 MODULE_LICENSE("GPL v2");