xref: /linux/drivers/net/usb/cx82310_eth.c (revision 2d87650a3bf1b80f7d0d150ee1af3f8a89e5b7aa)
1 /*
2  * Driver for USB ethernet port of Conexant CX82310-based ADSL routers
3  * Copyright (C) 2010 by Ondrej Zary
4  * some parts inspired by the cxacru driver
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/netdevice.h>
23 #include <linux/etherdevice.h>
24 #include <linux/ethtool.h>
25 #include <linux/workqueue.h>
26 #include <linux/mii.h>
27 #include <linux/usb.h>
28 #include <linux/usb/usbnet.h>
29 
30 enum cx82310_cmd {
31 	CMD_START		= 0x84,	/* no effect? */
32 	CMD_STOP		= 0x85,	/* no effect? */
33 	CMD_GET_STATUS		= 0x90,	/* returns nothing? */
34 	CMD_GET_MAC_ADDR	= 0x91,	/* read MAC address */
35 	CMD_GET_LINK_STATUS	= 0x92,	/* not useful, link is always up */
36 	CMD_ETHERNET_MODE	= 0x99,	/* unknown, needed during init */
37 };
38 
39 enum cx82310_status {
40 	STATUS_UNDEFINED,
41 	STATUS_SUCCESS,
42 	STATUS_ERROR,
43 	STATUS_UNSUPPORTED,
44 	STATUS_UNIMPLEMENTED,
45 	STATUS_PARAMETER_ERROR,
46 	STATUS_DBG_LOOPBACK,
47 };
48 
49 #define CMD_PACKET_SIZE	64
50 /* first command after power on can take around 8 seconds */
51 #define CMD_TIMEOUT	15000
52 #define CMD_REPLY_RETRY 5
53 
54 #define CX82310_MTU	1514
55 #define CMD_EP		0x01
56 
57 /*
58  * execute control command
59  *  - optionally send some data (command parameters)
60  *  - optionally wait for the reply
61  *  - optionally read some data from the reply
62  */
63 static int cx82310_cmd(struct usbnet *dev, enum cx82310_cmd cmd, bool reply,
64 		       u8 *wdata, int wlen, u8 *rdata, int rlen)
65 {
66 	int actual_len, retries, ret;
67 	struct usb_device *udev = dev->udev;
68 	u8 *buf = kzalloc(CMD_PACKET_SIZE, GFP_KERNEL);
69 
70 	if (!buf)
71 		return -ENOMEM;
72 
73 	/* create command packet */
74 	buf[0] = cmd;
75 	if (wdata)
76 		memcpy(buf + 4, wdata, min_t(int, wlen, CMD_PACKET_SIZE - 4));
77 
78 	/* send command packet */
79 	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, CMD_EP), buf,
80 			   CMD_PACKET_SIZE, &actual_len, CMD_TIMEOUT);
81 	if (ret < 0) {
82 		dev_err(&dev->udev->dev, "send command %#x: error %d\n",
83 			cmd, ret);
84 		goto end;
85 	}
86 
87 	if (reply) {
88 		/* wait for reply, retry if it's empty */
89 		for (retries = 0; retries < CMD_REPLY_RETRY; retries++) {
90 			ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, CMD_EP),
91 					   buf, CMD_PACKET_SIZE, &actual_len,
92 					   CMD_TIMEOUT);
93 			if (ret < 0) {
94 				dev_err(&dev->udev->dev,
95 					"reply receive error %d\n", ret);
96 				goto end;
97 			}
98 			if (actual_len > 0)
99 				break;
100 		}
101 		if (actual_len == 0) {
102 			dev_err(&dev->udev->dev, "no reply to command %#x\n",
103 				cmd);
104 			ret = -EIO;
105 			goto end;
106 		}
107 		if (buf[0] != cmd) {
108 			dev_err(&dev->udev->dev,
109 				"got reply to command %#x, expected: %#x\n",
110 				buf[0], cmd);
111 			ret = -EIO;
112 			goto end;
113 		}
114 		if (buf[1] != STATUS_SUCCESS) {
115 			dev_err(&dev->udev->dev, "command %#x failed: %#x\n",
116 				cmd, buf[1]);
117 			ret = -EIO;
118 			goto end;
119 		}
120 		if (rdata)
121 			memcpy(rdata, buf + 4,
122 			       min_t(int, rlen, CMD_PACKET_SIZE - 4));
123 	}
124 end:
125 	kfree(buf);
126 	return ret;
127 }
128 
129 #define partial_len	data[0]		/* length of partial packet data */
130 #define partial_rem	data[1]		/* remaining (missing) data length */
131 #define partial_data	data[2]		/* partial packet data */
132 
133 static int cx82310_bind(struct usbnet *dev, struct usb_interface *intf)
134 {
135 	int ret;
136 	char buf[15];
137 	struct usb_device *udev = dev->udev;
138 
139 	/* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
140 	if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
141 	    && strcmp(buf, "USB NET CARD")) {
142 		dev_info(&udev->dev, "ignoring: probably an ADSL modem\n");
143 		return -ENODEV;
144 	}
145 
146 	ret = usbnet_get_endpoints(dev, intf);
147 	if (ret)
148 		return ret;
149 
150 	/*
151 	 * this must not include ethernet header as the device can send partial
152 	 * packets with no header (and sometimes even empty URBs)
153 	 */
154 	dev->net->hard_header_len = 0;
155 	/* we can send at most 1514 bytes of data (+ 2-byte header) per URB */
156 	dev->hard_mtu = CX82310_MTU + 2;
157 	/* we can receive URBs up to 4KB from the device */
158 	dev->rx_urb_size = 4096;
159 
160 	dev->partial_data = (unsigned long) kmalloc(dev->hard_mtu, GFP_KERNEL);
161 	if (!dev->partial_data)
162 		return -ENOMEM;
163 
164 	/* enable ethernet mode (?) */
165 	ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
166 	if (ret) {
167 		dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
168 			ret);
169 		goto err;
170 	}
171 
172 	/* get the MAC address */
173 	ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
174 			  dev->net->dev_addr, ETH_ALEN);
175 	if (ret) {
176 		dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
177 		goto err;
178 	}
179 
180 	/* start (does not seem to have any effect?) */
181 	ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
182 	if (ret)
183 		goto err;
184 
185 	return 0;
186 err:
187 	kfree((void *)dev->partial_data);
188 	return ret;
189 }
190 
191 static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
192 {
193 	kfree((void *)dev->partial_data);
194 }
195 
196 /*
197  * RX is NOT easy - we can receive multiple packets per skb, each having 2-byte
198  * packet length at the beginning.
199  * The last packet might be incomplete (when it crosses the 4KB URB size),
200  * continuing in the next skb (without any headers).
201  * If a packet has odd length, there is one extra byte at the end (before next
202  * packet or at the end of the URB).
203  */
204 static int cx82310_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
205 {
206 	int len;
207 	struct sk_buff *skb2;
208 
209 	/*
210 	 * If the last skb ended with an incomplete packet, this skb contains
211 	 * end of that packet at the beginning.
212 	 */
213 	if (dev->partial_rem) {
214 		len = dev->partial_len + dev->partial_rem;
215 		skb2 = alloc_skb(len, GFP_ATOMIC);
216 		if (!skb2)
217 			return 0;
218 		skb_put(skb2, len);
219 		memcpy(skb2->data, (void *)dev->partial_data,
220 		       dev->partial_len);
221 		memcpy(skb2->data + dev->partial_len, skb->data,
222 		       dev->partial_rem);
223 		usbnet_skb_return(dev, skb2);
224 		skb_pull(skb, (dev->partial_rem + 1) & ~1);
225 		dev->partial_rem = 0;
226 		if (skb->len < 2)
227 			return 1;
228 	}
229 
230 	/* a skb can contain multiple packets */
231 	while (skb->len > 1) {
232 		/* first two bytes are packet length */
233 		len = skb->data[0] | (skb->data[1] << 8);
234 		skb_pull(skb, 2);
235 
236 		/* if last packet in the skb, let usbnet to process it */
237 		if (len == skb->len || len + 1 == skb->len) {
238 			skb_trim(skb, len);
239 			break;
240 		}
241 
242 		if (len > CX82310_MTU) {
243 			dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
244 				len);
245 			return 0;
246 		}
247 
248 		/* incomplete packet, save it for the next skb */
249 		if (len > skb->len) {
250 			dev->partial_len = skb->len;
251 			dev->partial_rem = len - skb->len;
252 			memcpy((void *)dev->partial_data, skb->data,
253 			       dev->partial_len);
254 			skb_pull(skb, skb->len);
255 			break;
256 		}
257 
258 		skb2 = alloc_skb(len, GFP_ATOMIC);
259 		if (!skb2)
260 			return 0;
261 		skb_put(skb2, len);
262 		memcpy(skb2->data, skb->data, len);
263 		/* process the packet */
264 		usbnet_skb_return(dev, skb2);
265 
266 		skb_pull(skb, (len + 1) & ~1);
267 	}
268 
269 	/* let usbnet process the last packet */
270 	return 1;
271 }
272 
273 /* TX is easy, just add 2 bytes of length at the beginning */
274 static struct sk_buff *cx82310_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
275 				       gfp_t flags)
276 {
277 	int len = skb->len;
278 
279 	if (skb_headroom(skb) < 2) {
280 		struct sk_buff *skb2 = skb_copy_expand(skb, 2, 0, flags);
281 		dev_kfree_skb_any(skb);
282 		skb = skb2;
283 		if (!skb)
284 			return NULL;
285 	}
286 	skb_push(skb, 2);
287 
288 	skb->data[0] = len;
289 	skb->data[1] = len >> 8;
290 
291 	return skb;
292 }
293 
294 
295 static const struct driver_info	cx82310_info = {
296 	.description	= "Conexant CX82310 USB ethernet",
297 	.flags		= FLAG_ETHER,
298 	.bind		= cx82310_bind,
299 	.unbind		= cx82310_unbind,
300 	.rx_fixup	= cx82310_rx_fixup,
301 	.tx_fixup	= cx82310_tx_fixup,
302 };
303 
304 static const struct usb_device_id products[] = {
305 	{
306 		USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0),
307 		.driver_info = (unsigned long) &cx82310_info
308 	},
309 	{ },
310 };
311 MODULE_DEVICE_TABLE(usb, products);
312 
313 static struct usb_driver cx82310_driver = {
314 	.name		= "cx82310_eth",
315 	.id_table	= products,
316 	.probe		= usbnet_probe,
317 	.disconnect	= usbnet_disconnect,
318 	.suspend	= usbnet_suspend,
319 	.resume		= usbnet_resume,
320 	.disable_hub_initiated_lpm = 1,
321 };
322 
323 module_usb_driver(cx82310_driver);
324 
325 MODULE_AUTHOR("Ondrej Zary");
326 MODULE_DESCRIPTION("Conexant CX82310-based ADSL router USB ethernet driver");
327 MODULE_LICENSE("GPL");
328