Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Ethernet interface part of the LG VL600 LTE modem (4G dongle)
0004  *
0005  * Copyright (C) 2011 Intel Corporation
0006  * Author: Andrzej Zaborowski <balrogg@gmail.com>
0007  */
0008 #include <linux/etherdevice.h>
0009 #include <linux/ethtool.h>
0010 #include <linux/mii.h>
0011 #include <linux/usb.h>
0012 #include <linux/usb/cdc.h>
0013 #include <linux/usb/usbnet.h>
0014 #include <linux/if_ether.h>
0015 #include <linux/if_arp.h>
0016 #include <linux/inetdevice.h>
0017 #include <linux/module.h>
0018 
0019 /*
0020  * The device has a CDC ACM port for modem control (it claims to be
0021  * CDC ACM anyway) and a CDC Ethernet port for actual network data.
0022  * It will however ignore data on both ports that is not encapsulated
0023  * in a specific way, any data returned is also encapsulated the same
0024  * way.  The headers don't seem to follow any popular standard.
0025  *
0026  * This driver adds and strips these headers from the ethernet frames
0027  * sent/received from the CDC Ethernet port.  The proprietary header
0028  * replaces the standard ethernet header in a packet so only actual
0029  * ethernet frames are allowed.  The headers allow some form of
0030  * multiplexing by using non standard values of the .h_proto field.
0031  * Windows/Mac drivers do send a couple of such frames to the device
0032  * during initialisation, with protocol set to 0x0906 or 0x0b06 and (what
0033  * seems to be) a flag in the .dummy_flags.  This doesn't seem necessary
0034  * for modem operation but can possibly be used for GPS or other functions.
0035  */
0036 
0037 struct vl600_frame_hdr {
0038     __le32 len;
0039     __le32 serial;
0040     __le32 pkt_cnt;
0041     __le32 dummy_flags;
0042     __le32 dummy;
0043     __le32 magic;
0044 } __attribute__((packed));
0045 
0046 struct vl600_pkt_hdr {
0047     __le32 dummy[2];
0048     __le32 len;
0049     __be16 h_proto;
0050 } __attribute__((packed));
0051 
0052 struct vl600_state {
0053     struct sk_buff *current_rx_buf;
0054 };
0055 
0056 static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
0057 {
0058     int ret;
0059     struct vl600_state *s = kzalloc(sizeof(struct vl600_state), GFP_KERNEL);
0060 
0061     if (!s)
0062         return -ENOMEM;
0063 
0064     ret = usbnet_cdc_bind(dev, intf);
0065     if (ret) {
0066         kfree(s);
0067         return ret;
0068     }
0069 
0070     dev->driver_priv = s;
0071 
0072     /* ARP packets don't go through, but they're also of no use.  The
0073      * subnet has only two hosts anyway: us and the gateway / DHCP
0074      * server (probably simulated by modem firmware or network operator)
0075      * whose address changes every time we connect to the intarwebz and
0076      * who doesn't bother answering ARP requests either.  So hardware
0077      * addresses have no meaning, the destination and the source of every
0078      * packet depend only on whether it is on the IN or OUT endpoint.  */
0079     dev->net->flags |= IFF_NOARP;
0080     /* IPv6 NDP relies on multicast.  Enable it by default. */
0081     dev->net->flags |= IFF_MULTICAST;
0082 
0083     return ret;
0084 }
0085 
0086 static void vl600_unbind(struct usbnet *dev, struct usb_interface *intf)
0087 {
0088     struct vl600_state *s = dev->driver_priv;
0089 
0090     dev_kfree_skb(s->current_rx_buf);
0091     kfree(s);
0092 
0093     return usbnet_cdc_unbind(dev, intf);
0094 }
0095 
0096 static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
0097 {
0098     struct vl600_frame_hdr *frame;
0099     struct vl600_pkt_hdr *packet;
0100     struct ethhdr *ethhdr;
0101     int packet_len, count;
0102     struct sk_buff *buf = skb;
0103     struct sk_buff *clone;
0104     struct vl600_state *s = dev->driver_priv;
0105 
0106     /* Frame lengths are generally 4B multiplies but every couple of
0107      * hours there's an odd number of bytes sized yet correct frame,
0108      * so don't require this.  */
0109 
0110     /* Allow a packet (or multiple packets batched together) to be
0111      * split across many frames.  We don't allow a new batch to
0112      * begin in the same frame another one is ending however, and no
0113      * leading or trailing pad bytes.  */
0114     if (s->current_rx_buf) {
0115         frame = (struct vl600_frame_hdr *) s->current_rx_buf->data;
0116         if (skb->len + s->current_rx_buf->len >
0117                 le32_to_cpup(&frame->len)) {
0118             netif_err(dev, ifup, dev->net, "Fragment too long\n");
0119             dev->net->stats.rx_length_errors++;
0120             goto error;
0121         }
0122 
0123         buf = s->current_rx_buf;
0124         skb_put_data(buf, skb->data, skb->len);
0125     } else if (skb->len < 4) {
0126         netif_err(dev, ifup, dev->net, "Frame too short\n");
0127         dev->net->stats.rx_length_errors++;
0128         goto error;
0129     }
0130 
0131     frame = (struct vl600_frame_hdr *) buf->data;
0132     /* Yes, check that frame->magic == 0x53544448 (or 0x44544d48),
0133      * otherwise we may run out of memory w/a bad packet */
0134     if (ntohl(frame->magic) != 0x53544448 &&
0135             ntohl(frame->magic) != 0x44544d48)
0136         goto error;
0137 
0138     if (buf->len < sizeof(*frame) ||
0139             buf->len != le32_to_cpup(&frame->len)) {
0140         /* Save this fragment for later assembly */
0141         if (s->current_rx_buf)
0142             return 0;
0143 
0144         s->current_rx_buf = skb_copy_expand(skb, 0,
0145                 le32_to_cpup(&frame->len), GFP_ATOMIC);
0146         if (!s->current_rx_buf)
0147             dev->net->stats.rx_errors++;
0148 
0149         return 0;
0150     }
0151 
0152     count = le32_to_cpup(&frame->pkt_cnt);
0153 
0154     skb_pull(buf, sizeof(*frame));
0155 
0156     while (count--) {
0157         if (buf->len < sizeof(*packet)) {
0158             netif_err(dev, ifup, dev->net, "Packet too short\n");
0159             goto error;
0160         }
0161 
0162         packet = (struct vl600_pkt_hdr *) buf->data;
0163         packet_len = sizeof(*packet) + le32_to_cpup(&packet->len);
0164         if (packet_len > buf->len) {
0165             netif_err(dev, ifup, dev->net,
0166                     "Bad packet length stored in header\n");
0167             goto error;
0168         }
0169 
0170         /* Packet header is same size as the ethernet header
0171          * (sizeof(*packet) == sizeof(*ethhdr)), additionally
0172          * the h_proto field is in the same place so we just leave it
0173          * alone and fill in the remaining fields.
0174          */
0175         ethhdr = (struct ethhdr *) skb->data;
0176         if (be16_to_cpup(&ethhdr->h_proto) == ETH_P_ARP &&
0177                 buf->len > 0x26) {
0178             /* Copy the addresses from packet contents */
0179             memcpy(ethhdr->h_source,
0180                     &buf->data[sizeof(*ethhdr) + 0x8],
0181                     ETH_ALEN);
0182             memcpy(ethhdr->h_dest,
0183                     &buf->data[sizeof(*ethhdr) + 0x12],
0184                     ETH_ALEN);
0185         } else {
0186             eth_zero_addr(ethhdr->h_source);
0187             memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
0188 
0189             /* Inbound IPv6 packets have an IPv4 ethertype (0x800)
0190              * for some reason.  Peek at the L3 header to check
0191              * for IPv6 packets, and set the ethertype to IPv6
0192              * (0x86dd) so Linux can understand it.
0193              */
0194             if ((buf->data[sizeof(*ethhdr)] & 0xf0) == 0x60)
0195                 ethhdr->h_proto = htons(ETH_P_IPV6);
0196         }
0197 
0198         if (count) {
0199             /* Not the last packet in this batch */
0200             clone = skb_clone(buf, GFP_ATOMIC);
0201             if (!clone)
0202                 goto error;
0203 
0204             skb_trim(clone, packet_len);
0205             usbnet_skb_return(dev, clone);
0206 
0207             skb_pull(buf, (packet_len + 3) & ~3);
0208         } else {
0209             skb_trim(buf, packet_len);
0210 
0211             if (s->current_rx_buf) {
0212                 usbnet_skb_return(dev, buf);
0213                 s->current_rx_buf = NULL;
0214                 return 0;
0215             }
0216 
0217             return 1;
0218         }
0219     }
0220 
0221 error:
0222     if (s->current_rx_buf) {
0223         dev_kfree_skb_any(s->current_rx_buf);
0224         s->current_rx_buf = NULL;
0225     }
0226     dev->net->stats.rx_errors++;
0227     return 0;
0228 }
0229 
0230 static struct sk_buff *vl600_tx_fixup(struct usbnet *dev,
0231         struct sk_buff *skb, gfp_t flags)
0232 {
0233     struct sk_buff *ret;
0234     struct vl600_frame_hdr *frame;
0235     struct vl600_pkt_hdr *packet;
0236     static uint32_t serial = 1;
0237     int orig_len = skb->len - sizeof(struct ethhdr);
0238     int full_len = (skb->len + sizeof(struct vl600_frame_hdr) + 3) & ~3;
0239 
0240     frame = (struct vl600_frame_hdr *) skb->data;
0241     if (skb->len > sizeof(*frame) && skb->len == le32_to_cpup(&frame->len))
0242         return skb; /* Already encapsulated? */
0243 
0244     if (skb->len < sizeof(struct ethhdr))
0245         /* Drop, device can only deal with ethernet packets */
0246         return NULL;
0247 
0248     if (!skb_cloned(skb)) {
0249         int headroom = skb_headroom(skb);
0250         int tailroom = skb_tailroom(skb);
0251 
0252         if (tailroom >= full_len - skb->len - sizeof(*frame) &&
0253                 headroom >= sizeof(*frame))
0254             /* There's enough head and tail room */
0255             goto encapsulate;
0256 
0257         if (headroom + tailroom + skb->len >= full_len) {
0258             /* There's enough total room, just readjust */
0259             skb->data = memmove(skb->head + sizeof(*frame),
0260                     skb->data, skb->len);
0261             skb_set_tail_pointer(skb, skb->len);
0262             goto encapsulate;
0263         }
0264     }
0265 
0266     /* Alloc a new skb with the required size */
0267     ret = skb_copy_expand(skb, sizeof(struct vl600_frame_hdr), full_len -
0268             skb->len - sizeof(struct vl600_frame_hdr), flags);
0269     dev_kfree_skb_any(skb);
0270     if (!ret)
0271         return ret;
0272     skb = ret;
0273 
0274 encapsulate:
0275     /* Packet header is same size as ethernet packet header
0276      * (sizeof(*packet) == sizeof(struct ethhdr)), additionally the
0277      * h_proto field is in the same place so we just leave it alone and
0278      * overwrite the remaining fields.
0279      */
0280     packet = (struct vl600_pkt_hdr *) skb->data;
0281     /* The VL600 wants IPv6 packets to have an IPv4 ethertype
0282      * Since this modem only supports IPv4 and IPv6, just set all
0283      * frames to 0x0800 (ETH_P_IP)
0284      */
0285     packet->h_proto = htons(ETH_P_IP);
0286     memset(&packet->dummy, 0, sizeof(packet->dummy));
0287     packet->len = cpu_to_le32(orig_len);
0288 
0289     frame = skb_push(skb, sizeof(*frame));
0290     memset(frame, 0, sizeof(*frame));
0291     frame->len = cpu_to_le32(full_len);
0292     frame->serial = cpu_to_le32(serial++);
0293     frame->pkt_cnt = cpu_to_le32(1);
0294 
0295     if (skb->len < full_len) /* Pad */
0296         skb_put(skb, full_len - skb->len);
0297 
0298     return skb;
0299 }
0300 
0301 static const struct driver_info vl600_info = {
0302     .description    = "LG VL600 modem",
0303     .flags      = FLAG_RX_ASSEMBLE | FLAG_WWAN,
0304     .bind       = vl600_bind,
0305     .unbind     = vl600_unbind,
0306     .status     = usbnet_cdc_status,
0307     .rx_fixup   = vl600_rx_fixup,
0308     .tx_fixup   = vl600_tx_fixup,
0309 };
0310 
0311 static const struct usb_device_id products[] = {
0312     {
0313         USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
0314                 USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
0315         .driver_info    = (unsigned long) &vl600_info,
0316     },
0317     {}, /* End */
0318 };
0319 MODULE_DEVICE_TABLE(usb, products);
0320 
0321 static struct usb_driver lg_vl600_driver = {
0322     .name       = "lg-vl600",
0323     .id_table   = products,
0324     .probe      = usbnet_probe,
0325     .disconnect = usbnet_disconnect,
0326     .suspend    = usbnet_suspend,
0327     .resume     = usbnet_resume,
0328     .disable_hub_initiated_lpm = 1,
0329 };
0330 
0331 module_usb_driver(lg_vl600_driver);
0332 
0333 MODULE_AUTHOR("Anrzej Zaborowski");
0334 MODULE_DESCRIPTION("LG-VL600 modem's ethernet link");
0335 MODULE_LICENSE("GPL");