Blame view

drivers/net/usb/zaurus.c 11.7 KB
0aa599c56   David Brownell   [PATCH] USB: usbn...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
   * Copyright (C) 2002-2005 by David Brownell
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
9cb00073d   Jeff Kirsher   usb: Fix FSF addr...
16
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
0aa599c56   David Brownell   [PATCH] USB: usbn...
17
18
19
20
   */
  
  // #define	DEBUG			// error path messages, extra info
  // #define	VERBOSE			// more; success messages
0aa599c56   David Brownell   [PATCH] USB: usbn...
21
  #include <linux/module.h>
0aa599c56   David Brownell   [PATCH] USB: usbn...
22
23
24
25
26
27
  #include <linux/netdevice.h>
  #include <linux/ethtool.h>
  #include <linux/workqueue.h>
  #include <linux/mii.h>
  #include <linux/crc32.h>
  #include <linux/usb.h>
a8c28f238   David Brownell   [PATCH] USB: move...
28
  #include <linux/usb/cdc.h>
3692e94f1   Jussi Kivilinna   Move usbnet.h and...
29
  #include <linux/usb/usbnet.h>
0aa599c56   David Brownell   [PATCH] USB: usbn...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  
  
  /*
   * All known Zaurii lie about their standards conformance.  At least
   * the earliest SA-1100 models lie by saying they support CDC Ethernet.
   * Some later models (especially PXA-25x and PXA-27x based ones) lie
   * and say they support CDC MDLM (for access to cell phone modems).
   *
   * There are non-Zaurus products that use these same protocols too.
   *
   * The annoying thing is that at the same time Sharp was developing
   * that annoying standards-breaking software, the Linux community had
   * a simple "CDC Subset" working reliably on the same SA-1100 hardware.
   * That is, the same functionality but not violating standards.
   *
   * The CDC Ethernet nonconformance points are troublesome to hosts
   * with a true CDC Ethernet implementation:
   *   - Framing appends a CRC, which the spec says drivers "must not" do;
   *   - Transfers data in altsetting zero, instead of altsetting 1;
   *   - All these peripherals use the same ethernet address.
   *
   * The CDC MDLM nonconformance is less immediately troublesome, since all
   * MDLM implementations are quasi-proprietary anyway.
   */
  
  static struct sk_buff *
55016f10e   Al Viro   [PATCH] gfp_t: dr...
56
  zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
0aa599c56   David Brownell   [PATCH] USB: usbn...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  {
  	int			padlen;
  	struct sk_buff		*skb2;
  
  	padlen = 2;
  	if (!skb_cloned(skb)) {
  		int	tailroom = skb_tailroom(skb);
  		if ((padlen + 4) <= tailroom)
  			goto done;
  	}
  	skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
  	dev_kfree_skb_any(skb);
  	skb = skb2;
  	if (skb) {
  		u32		fcs;
  done:
  		fcs = crc32_le(~0, skb->data, skb->len);
  		fcs = ~fcs;
  
  		*skb_put (skb, 1) = fcs       & 0xff;
  		*skb_put (skb, 1) = (fcs>> 8) & 0xff;
  		*skb_put (skb, 1) = (fcs>>16) & 0xff;
  		*skb_put (skb, 1) = (fcs>>24) & 0xff;
  	}
  	return skb;
  }
  
  static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
  {
  	/* Belcarra's funky framing has other options; mostly
  	 * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
  	 */
  	dev->net->hard_header_len += 6;
  	dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
  	return usbnet_generic_cdc_bind(dev, intf);
  }
  
  /* PDA style devices are always connected if present */
  static int always_connected (struct usbnet *dev)
  {
  	return 0;
  }
  
  static const struct driver_info	zaurus_sl5x00_info = {
  	.description =	"Sharp Zaurus SL-5x00",
c261344d3   Arnd Bergmann   usbnet: use eth%d...
102
  	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0aa599c56   David Brownell   [PATCH] USB: usbn...
103
104
105
  	.check_connect = always_connected,
  	.bind =		zaurus_bind,
  	.unbind =	usbnet_cdc_unbind,
f44f725f7   David Brownell   [PATCH] USB: usbn...
106
  	.tx_fixup =	zaurus_tx_fixup,
0aa599c56   David Brownell   [PATCH] USB: usbn...
107
108
109
110
111
  };
  #define	ZAURUS_STRONGARM_INFO	((unsigned long)&zaurus_sl5x00_info)
  
  static const struct driver_info	zaurus_pxa_info = {
  	.description =	"Sharp Zaurus, PXA-2xx based",
c261344d3   Arnd Bergmann   usbnet: use eth%d...
112
  	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0aa599c56   David Brownell   [PATCH] USB: usbn...
113
114
115
  	.check_connect = always_connected,
  	.bind =		zaurus_bind,
  	.unbind =	usbnet_cdc_unbind,
f44f725f7   David Brownell   [PATCH] USB: usbn...
116
  	.tx_fixup =	zaurus_tx_fixup,
0aa599c56   David Brownell   [PATCH] USB: usbn...
117
118
119
120
121
  };
  #define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
  
  static const struct driver_info	olympus_mxl_info = {
  	.description =	"Olympus R1000",
c261344d3   Arnd Bergmann   usbnet: use eth%d...
122
  	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0aa599c56   David Brownell   [PATCH] USB: usbn...
123
124
125
  	.check_connect = always_connected,
  	.bind =		zaurus_bind,
  	.unbind =	usbnet_cdc_unbind,
f44f725f7   David Brownell   [PATCH] USB: usbn...
126
  	.tx_fixup =	zaurus_tx_fixup,
0aa599c56   David Brownell   [PATCH] USB: usbn...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  };
  #define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)
  
  
  /* Some more recent products using Lineo/Belcarra code will wrongly claim
   * CDC MDLM conformance.  They aren't conformant:  data endpoints live
   * in the control interface, there's no data interface, and it's not used
   * to talk to a cell phone radio.  But at least we can detect these two
   * pseudo-classes, rather than growing this product list with entries for
   * each new nonconformant product (sigh).
   */
  static const u8 safe_guid[16] = {
  	0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
  	0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
  };
  static const u8 blan_guid[16] = {
  	0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
  	0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
  };
  
  static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
  {
  	u8				*buf = intf->cur_altsetting->extra;
  	int				len = intf->cur_altsetting->extralen;
  	struct usb_cdc_mdlm_desc	*desc = NULL;
  	struct usb_cdc_mdlm_detail_desc	*detail = NULL;
  
  	while (len > 3) {
  		if (buf [1] != USB_DT_CS_INTERFACE)
  			goto next_desc;
  
  		/* use bDescriptorSubType, and just verify that we get a
  		 * "BLAN" (or "SAFE") descriptor.
  		 */
  		switch (buf [2]) {
  		case USB_CDC_MDLM_TYPE:
  			if (desc) {
  				dev_dbg(&intf->dev, "extra MDLM
  ");
  				goto bad_desc;
  			}
  			desc = (void *) buf;
  			if (desc->bLength != sizeof *desc) {
  				dev_dbg(&intf->dev, "MDLM len %u
  ",
  					desc->bLength);
  				goto bad_desc;
  			}
  			/* expect bcdVersion 1.0, ignore */
8e95a2026   Joe Perches   drivers/net: Move...
176
177
  			if (memcmp(&desc->bGUID, blan_guid, 16) &&
  			    memcmp(&desc->bGUID, safe_guid, 16)) {
0aa599c56   David Brownell   [PATCH] USB: usbn...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  				/* hey, this one might _really_ be MDLM! */
  				dev_dbg(&intf->dev, "MDLM guid
  ");
  				goto bad_desc;
  			}
  			break;
  		case USB_CDC_MDLM_DETAIL_TYPE:
  			if (detail) {
  				dev_dbg(&intf->dev, "extra MDLM detail
  ");
  				goto bad_desc;
  			}
  			detail = (void *) buf;
  			switch (detail->bGuidDescriptorType) {
  			case 0:			/* "SAFE" */
  				if (detail->bLength != (sizeof *detail + 2))
  					goto bad_detail;
  				break;
  			case 1:			/* "BLAN" */
  				if (detail->bLength != (sizeof *detail + 3))
  					goto bad_detail;
  				break;
  			default:
  				goto bad_detail;
  			}
  
  			/* assuming we either noticed BLAN already, or will
  			 * find it soon, there are some data bytes here:
  			 *  - bmNetworkCapabilities (unused)
  			 *  - bmDataCapabilities (bits, see below)
  			 *  - bPad (ignored, for PADAFTER -- BLAN-only)
  			 * bits are:
  			 *  - 0x01 -- Zaurus framing (add CRC)
  			 *  - 0x02 -- PADBEFORE (CRC includes some padding)
  			 *  - 0x04 -- PADAFTER (some padding after CRC)
  			 *  - 0x08 -- "fermat" packet mangling (for hw bugs)
  			 * the PADBEFORE appears not to matter; we interop
  			 * with devices that use it and those that don't.
  			 */
  			if ((detail->bDetailData[1] & ~0x02) != 0x01) {
7f927fcc2   Alexey Dobriyan   [PATCH] Typo fixes
218
  				/* bmDataCapabilities == 0 would be fine too,
0aa599c56   David Brownell   [PATCH] USB: usbn...
219
220
221
222
223
224
225
226
227
228
229
  				 * but framing is minidriver-coupled for now.
  				 */
  bad_detail:
  				dev_dbg(&intf->dev,
  						"bad MDLM detail, %d %d %d
  ",
  						detail->bLength,
  						detail->bDetailData[0],
  						detail->bDetailData[2]);
  				goto bad_desc;
  			}
f44f725f7   David Brownell   [PATCH] USB: usbn...
230
231
232
233
234
  
  			/* same extra framing as for non-BLAN mode */
  			dev->net->hard_header_len += 6;
  			dev->rx_urb_size = dev->net->hard_header_len
  					+ dev->net->mtu;
0aa599c56   David Brownell   [PATCH] USB: usbn...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  			break;
  		}
  next_desc:
  		len -= buf [0];	/* bLength */
  		buf += buf [0];
  	}
  
  	if (!desc || !detail) {
  		dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor
  ",
  			desc ? "" : "func ",
  			detail ? "" : "detail ");
  		goto bad_desc;
  	}
  
  	/* There's probably a CDC Ethernet descriptor there, but we can't
  	 * rely on the Ethernet address it provides since not all vendors
  	 * bother to make it unique.  Likewise there's no point in tracking
  	 * of the CDC event notifications.
  	 */
  	return usbnet_get_endpoints(dev, intf);
  
  bad_desc:
  	dev_info(&dev->udev->dev, "unsupported MDLM descriptors
  ");
  	return -ENODEV;
  }
  
  static const struct driver_info	bogus_mdlm_info = {
  	.description =	"pseudo-MDLM (BLAN) device",
c261344d3   Arnd Bergmann   usbnet: use eth%d...
265
  	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0aa599c56   David Brownell   [PATCH] USB: usbn...
266
  	.check_connect = always_connected,
f44f725f7   David Brownell   [PATCH] USB: usbn...
267
  	.tx_fixup =	zaurus_tx_fixup,
0aa599c56   David Brownell   [PATCH] USB: usbn...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	.bind =		blan_mdlm_bind,
  };
  
  static const struct usb_device_id	products [] = {
  #define	ZAURUS_MASTER_INTERFACE \
  	.bInterfaceClass	= USB_CLASS_COMM, \
  	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
  	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
  
  /* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
  {
  	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
  			  | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor		= 0x04DD,
  	.idProduct		= 0x8004,
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_STRONGARM_INFO,
  },
  
  /* PXA-2xx based models are also lying-about-cdc.  If you add any
   * more devices that claim to be CDC Ethernet, make sure they get
   * added to the blacklist in cdc_ether too.
   *
   * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
   * unlike the older ones with 2.4 "embedix" kernels.
   */
  {
  	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
  			  | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor		= 0x04DD,
  	.idProduct		= 0x8005,	/* A-300 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  }, {
  	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
  			  | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor		= 0x04DD,
  	.idProduct		= 0x8006,	/* B-500/SL-5600 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  }, {
  	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
  	          | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor		= 0x04DD,
  	.idProduct		= 0x8007,	/* C-700 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  }, {
  	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
  		 | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor               = 0x04DD,
  	.idProduct              = 0x9031,	/* C-750 C-760 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  }, {
15103aa7a   Dave Jones   zaurus: Add ID fo...
323
324
325
326
327
  	/* C-750/C-760/C-860/SL-C3000 PDA in MDLM mode */
  	USB_DEVICE_AND_INTERFACE_INFO(0x04DD, 0x9031, USB_CLASS_COMM,
  			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
  	.driver_info = (unsigned long) &bogus_mdlm_info,
  }, {
0aa599c56   David Brownell   [PATCH] USB: usbn...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
  		 | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor               = 0x04DD,
  	.idProduct              = 0x9032,	/* SL-6000 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  }, {
  	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
  		 | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor               = 0x04DD,
  	/* reported with some C860 units */
  	.idProduct              = 0x9050,	/* C-860 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = ZAURUS_PXA_INFO,
  },
0aa599c56   David Brownell   [PATCH] USB: usbn...
343
  {
a2daf2631   Guan Xin   USB: Add Motorola...
344
345
346
347
348
  	/* Motorola Rokr E6 */
  	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
  			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
  	.driver_info = (unsigned long) &bogus_mdlm_info,
  }, {
52c0326be   Dmitriy Taychenachev   zaurus: add usb i...
349
350
351
352
  	/* Motorola MOTOMAGX phones */
  	USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
  			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
  	.driver_info = (unsigned long) &bogus_mdlm_info,
0aa599c56   David Brownell   [PATCH] USB: usbn...
353
354
355
356
357
358
359
360
361
362
363
364
365
  },
  
  /* Olympus has some models with a Zaurus-compatible option.
   * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
   */
  {
  	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
  		 | USB_DEVICE_ID_MATCH_DEVICE,
  	.idVendor               = 0x07B4,
  	.idProduct              = 0x0F02,	/* R-1000 */
  	ZAURUS_MASTER_INTERFACE,
  	.driver_info = OLYMPUS_MXL_INFO,
  },
ee932bf9a   Scott Talbert   Move Logitech Har...
366
367
368
369
370
371
372
  
  /* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */
  {
  	USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM,
  			USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
  	.driver_info = (unsigned long) &bogus_mdlm_info,
  },
0aa599c56   David Brownell   [PATCH] USB: usbn...
373
374
375
376
377
  	{ },		// END
  };
  MODULE_DEVICE_TABLE(usb, products);
  
  static struct usb_driver zaurus_driver = {
0aa599c56   David Brownell   [PATCH] USB: usbn...
378
379
380
381
382
383
  	.name =		"zaurus",
  	.id_table =	products,
  	.probe =	usbnet_probe,
  	.disconnect =	usbnet_disconnect,
  	.suspend =	usbnet_suspend,
  	.resume =	usbnet_resume,
e1f12eb6b   Sarah Sharp   USB: Disable hub-...
384
  	.disable_hub_initiated_lpm = 1,
0aa599c56   David Brownell   [PATCH] USB: usbn...
385
  };
d632eb1bf   Greg Kroah-Hartman   USB: convert driv...
386
  module_usb_driver(zaurus_driver);
0aa599c56   David Brownell   [PATCH] USB: usbn...
387
388
389
390
  
  MODULE_AUTHOR("Pavel Machek, David Brownell");
  MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
  MODULE_LICENSE("GPL");