This source file includes following definitions.
- eem_linkcmd_complete
- eem_linkcmd
- eem_bind
- eem_tx_fixup
- eem_rx_fixup
1
2
3
4
5
6
7
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/etherdevice.h>
11 #include <linux/ctype.h>
12 #include <linux/ethtool.h>
13 #include <linux/workqueue.h>
14 #include <linux/mii.h>
15 #include <linux/usb.h>
16 #include <linux/crc32.h>
17 #include <linux/usb/cdc.h>
18 #include <linux/usb/usbnet.h>
19 #include <linux/gfp.h>
20 #include <linux/if_vlan.h>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #define EEM_HEAD 2
38
39
40
41 static void eem_linkcmd_complete(struct urb *urb)
42 {
43 dev_kfree_skb(urb->context);
44 usb_free_urb(urb);
45 }
46
47 static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
48 {
49 struct urb *urb;
50 int status;
51
52 urb = usb_alloc_urb(0, GFP_ATOMIC);
53 if (!urb)
54 goto fail;
55
56 usb_fill_bulk_urb(urb, dev->udev, dev->out,
57 skb->data, skb->len, eem_linkcmd_complete, skb);
58
59 status = usb_submit_urb(urb, GFP_ATOMIC);
60 if (status) {
61 usb_free_urb(urb);
62 fail:
63 dev_kfree_skb(skb);
64 netdev_warn(dev->net, "link cmd failure\n");
65 return;
66 }
67 }
68
69 static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
70 {
71 int status = 0;
72
73 status = usbnet_get_endpoints(dev, intf);
74 if (status < 0)
75 return status;
76
77
78
79 dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
80 dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
81
82 return 0;
83 }
84
85
86
87
88
89 static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
90 gfp_t flags)
91 {
92 struct sk_buff *skb2 = NULL;
93 u16 len = skb->len;
94 u32 crc = 0;
95 int padlen = 0;
96
97
98
99
100
101
102
103 if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
104 padlen += 2;
105
106 if (!skb_cloned(skb)) {
107 int headroom = skb_headroom(skb);
108 int tailroom = skb_tailroom(skb);
109
110 if ((tailroom >= ETH_FCS_LEN + padlen) &&
111 (headroom >= EEM_HEAD))
112 goto done;
113
114 if ((headroom + tailroom)
115 > (EEM_HEAD + ETH_FCS_LEN + padlen)) {
116 skb->data = memmove(skb->head +
117 EEM_HEAD,
118 skb->data,
119 skb->len);
120 skb_set_tail_pointer(skb, len);
121 goto done;
122 }
123 }
124
125 skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
126 if (!skb2)
127 return NULL;
128
129 dev_kfree_skb_any(skb);
130 skb = skb2;
131
132 done:
133
134 crc = crc32_le(~0, skb->data, skb->len);
135 crc = ~crc;
136
137 put_unaligned_le32(crc, skb_put(skb, 4));
138
139
140
141
142
143
144 len = skb->len;
145 put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
146
147
148 if (padlen)
149 put_unaligned_le16(0, skb_put(skb, 2));
150
151 return skb;
152 }
153
154 static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
155 {
156
157
158
159
160
161
162
163
164
165
166
167 do {
168 struct sk_buff *skb2 = NULL;
169 u16 header;
170 u16 len = 0;
171
172
173 if (skb->len < EEM_HEAD)
174 return 0;
175
176
177
178
179
180
181 header = get_unaligned_le16(skb->data);
182 skb_pull(skb, EEM_HEAD);
183
184
185
186
187
188
189
190 if (header & BIT(15)) {
191 u16 bmEEMCmd;
192
193
194
195
196
197
198
199
200 if (header & BIT(14)) {
201 netdev_dbg(dev->net, "reserved command %04x\n",
202 header);
203 continue;
204 }
205
206 bmEEMCmd = (header >> 11) & 0x7;
207 switch (bmEEMCmd) {
208
209
210 case 0:
211 len = header & 0x7FF;
212
213
214 if (skb->len < len)
215 return 0;
216
217 skb2 = skb_clone(skb, GFP_ATOMIC);
218 if (unlikely(!skb2))
219 goto next;
220 skb_trim(skb2, len);
221 put_unaligned_le16(BIT(15) | (1 << 11) | len,
222 skb_push(skb2, 2));
223 eem_linkcmd(dev, skb2);
224 break;
225
226
227
228
229
230
231
232
233
234 case 2:
235 usbnet_device_suggests_idle(dev);
236 continue;
237 case 3:
238 case 4:
239 continue;
240
241
242
243
244
245
246 case 1:
247 case 5:
248 default:
249 netdev_warn(dev->net,
250 "unexpected link command %d\n",
251 bmEEMCmd);
252 continue;
253 }
254
255 } else {
256 u32 crc, crc2;
257 int is_last;
258
259
260 if (header == 0)
261 continue;
262
263
264
265
266
267
268
269 len = header & 0x3FFF;
270
271
272 if (skb->len < len)
273 return 0;
274
275
276 if (len < (ETH_HLEN + ETH_FCS_LEN))
277 goto next;
278
279
280
281
282
283
284
285
286 is_last = (len == skb->len);
287 if (is_last)
288 skb2 = skb;
289 else {
290 skb2 = skb_clone(skb, GFP_ATOMIC);
291 if (unlikely(!skb2))
292 return 0;
293 }
294
295
296
297
298
299
300
301 if (header & BIT(14)) {
302 crc = get_unaligned_le32(skb2->data
303 + len - ETH_FCS_LEN);
304 crc2 = ~crc32_le(~0, skb2->data, skb2->len
305 - ETH_FCS_LEN);
306 } else {
307 crc = get_unaligned_be32(skb2->data
308 + len - ETH_FCS_LEN);
309 crc2 = 0xdeadbeef;
310 }
311 skb_trim(skb2, len - ETH_FCS_LEN);
312
313 if (is_last)
314 return crc == crc2;
315
316 if (unlikely(crc != crc2)) {
317 dev->net->stats.rx_errors++;
318 dev_kfree_skb_any(skb2);
319 } else
320 usbnet_skb_return(dev, skb2);
321 }
322
323 next:
324 skb_pull(skb, len);
325 } while (skb->len);
326
327 return 1;
328 }
329
330 static const struct driver_info eem_info = {
331 .description = "CDC EEM Device",
332 .flags = FLAG_ETHER | FLAG_POINTTOPOINT,
333 .bind = eem_bind,
334 .rx_fixup = eem_rx_fixup,
335 .tx_fixup = eem_tx_fixup,
336 };
337
338
339
340 static const struct usb_device_id products[] = {
341 {
342 USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
343 USB_CDC_PROTO_EEM),
344 .driver_info = (unsigned long) &eem_info,
345 },
346 {
347
348 },
349 };
350 MODULE_DEVICE_TABLE(usb, products);
351
352 static struct usb_driver eem_driver = {
353 .name = "cdc_eem",
354 .id_table = products,
355 .probe = usbnet_probe,
356 .disconnect = usbnet_disconnect,
357 .suspend = usbnet_suspend,
358 .resume = usbnet_resume,
359 .disable_hub_initiated_lpm = 1,
360 };
361
362 module_usb_driver(eem_driver);
363
364 MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
365 MODULE_DESCRIPTION("USB CDC EEM");
366 MODULE_LICENSE("GPL");