0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/netdevice.h>
0012 #include <linux/ethtool.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/mii.h>
0015 #include <linux/crc32.h>
0016 #include <linux/usb.h>
0017 #include <linux/usb/cdc.h>
0018 #include <linux/usb/usbnet.h>
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 static struct sk_buff *
0045 zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
0046 {
0047 int padlen;
0048 struct sk_buff *skb2;
0049
0050 padlen = 2;
0051 if (!skb_cloned(skb)) {
0052 int tailroom = skb_tailroom(skb);
0053 if ((padlen + 4) <= tailroom)
0054 goto done;
0055 }
0056 skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
0057 dev_kfree_skb_any(skb);
0058 skb = skb2;
0059 if (skb) {
0060 u32 fcs;
0061 done:
0062 fcs = crc32_le(~0, skb->data, skb->len);
0063 fcs = ~fcs;
0064
0065 skb_put_u8(skb, fcs & 0xff);
0066 skb_put_u8(skb, (fcs >> 8) & 0xff);
0067 skb_put_u8(skb, (fcs >> 16) & 0xff);
0068 skb_put_u8(skb, (fcs >> 24) & 0xff);
0069 }
0070 return skb;
0071 }
0072
0073 static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
0074 {
0075
0076
0077
0078 dev->net->hard_header_len += 6;
0079 dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu;
0080 return usbnet_generic_cdc_bind(dev, intf);
0081 }
0082
0083
0084 static int always_connected (struct usbnet *dev)
0085 {
0086 return 0;
0087 }
0088
0089 static const struct driver_info zaurus_sl5x00_info = {
0090 .description = "Sharp Zaurus SL-5x00",
0091 .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0092 .check_connect = always_connected,
0093 .bind = zaurus_bind,
0094 .unbind = usbnet_cdc_unbind,
0095 .tx_fixup = zaurus_tx_fixup,
0096 };
0097 #define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info)
0098
0099 static const struct driver_info zaurus_pxa_info = {
0100 .description = "Sharp Zaurus, PXA-2xx based",
0101 .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0102 .check_connect = always_connected,
0103 .bind = zaurus_bind,
0104 .unbind = usbnet_cdc_unbind,
0105 .tx_fixup = zaurus_tx_fixup,
0106 };
0107 #define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
0108
0109 static const struct driver_info olympus_mxl_info = {
0110 .description = "Olympus R1000",
0111 .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0112 .check_connect = always_connected,
0113 .bind = zaurus_bind,
0114 .unbind = usbnet_cdc_unbind,
0115 .tx_fixup = zaurus_tx_fixup,
0116 };
0117 #define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info)
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 static const u8 safe_guid[16] = {
0128 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
0129 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
0130 };
0131 static const u8 blan_guid[16] = {
0132 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
0133 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
0134 };
0135
0136 static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
0137 {
0138 u8 *buf = intf->cur_altsetting->extra;
0139 int len = intf->cur_altsetting->extralen;
0140 struct usb_cdc_mdlm_desc *desc = NULL;
0141 struct usb_cdc_mdlm_detail_desc *detail = NULL;
0142
0143 while (len > 3) {
0144 if (buf [1] != USB_DT_CS_INTERFACE)
0145 goto next_desc;
0146
0147
0148
0149
0150 switch (buf [2]) {
0151 case USB_CDC_MDLM_TYPE:
0152 if (desc) {
0153 dev_dbg(&intf->dev, "extra MDLM\n");
0154 goto bad_desc;
0155 }
0156 desc = (void *) buf;
0157 if (desc->bLength != sizeof *desc) {
0158 dev_dbg(&intf->dev, "MDLM len %u\n",
0159 desc->bLength);
0160 goto bad_desc;
0161 }
0162
0163 if (memcmp(&desc->bGUID, blan_guid, 16) &&
0164 memcmp(&desc->bGUID, safe_guid, 16)) {
0165
0166 dev_dbg(&intf->dev, "MDLM guid\n");
0167 goto bad_desc;
0168 }
0169 break;
0170 case USB_CDC_MDLM_DETAIL_TYPE:
0171 if (detail) {
0172 dev_dbg(&intf->dev, "extra MDLM detail\n");
0173 goto bad_desc;
0174 }
0175 detail = (void *) buf;
0176 switch (detail->bGuidDescriptorType) {
0177 case 0:
0178 if (detail->bLength != (sizeof *detail + 2))
0179 goto bad_detail;
0180 break;
0181 case 1:
0182 if (detail->bLength != (sizeof *detail + 3))
0183 goto bad_detail;
0184 break;
0185 default:
0186 goto bad_detail;
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 if ((detail->bDetailData[1] & ~0x02) != 0x01) {
0203
0204
0205
0206 bad_detail:
0207 dev_dbg(&intf->dev,
0208 "bad MDLM detail, %d %d %d\n",
0209 detail->bLength,
0210 detail->bDetailData[0],
0211 detail->bDetailData[2]);
0212 goto bad_desc;
0213 }
0214
0215
0216 dev->net->hard_header_len += 6;
0217 dev->rx_urb_size = dev->net->hard_header_len
0218 + dev->net->mtu;
0219 break;
0220 }
0221 next_desc:
0222 len -= buf [0];
0223 buf += buf [0];
0224 }
0225
0226 if (!desc || !detail) {
0227 dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
0228 desc ? "" : "func ",
0229 detail ? "" : "detail ");
0230 goto bad_desc;
0231 }
0232
0233
0234
0235
0236
0237
0238 return usbnet_get_endpoints(dev, intf);
0239
0240 bad_desc:
0241 dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n");
0242 return -ENODEV;
0243 }
0244
0245 static const struct driver_info bogus_mdlm_info = {
0246 .description = "pseudo-MDLM (BLAN) device",
0247 .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
0248 .check_connect = always_connected,
0249 .tx_fixup = zaurus_tx_fixup,
0250 .bind = blan_mdlm_bind,
0251 };
0252
0253 static const struct usb_device_id products [] = {
0254 #define ZAURUS_MASTER_INTERFACE \
0255 .bInterfaceClass = USB_CLASS_COMM, \
0256 .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
0257 .bInterfaceProtocol = USB_CDC_PROTO_NONE
0258
0259 #define ZAURUS_FAKE_INTERFACE \
0260 .bInterfaceClass = USB_CLASS_COMM, \
0261 .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM, \
0262 .bInterfaceProtocol = USB_CDC_PROTO_NONE
0263
0264
0265 {
0266 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0267 | USB_DEVICE_ID_MATCH_DEVICE,
0268 .idVendor = 0x04DD,
0269 .idProduct = 0x8004,
0270 ZAURUS_MASTER_INTERFACE,
0271 .driver_info = ZAURUS_STRONGARM_INFO,
0272 },
0273
0274
0275
0276
0277
0278
0279
0280
0281 {
0282 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0283 | USB_DEVICE_ID_MATCH_DEVICE,
0284 .idVendor = 0x04DD,
0285 .idProduct = 0x8005,
0286 ZAURUS_MASTER_INTERFACE,
0287 .driver_info = ZAURUS_PXA_INFO,
0288 }, {
0289 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0290 | USB_DEVICE_ID_MATCH_DEVICE,
0291 .idVendor = 0x04DD,
0292 .idProduct = 0x8006,
0293 ZAURUS_MASTER_INTERFACE,
0294 .driver_info = ZAURUS_PXA_INFO,
0295 }, {
0296 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0297 | USB_DEVICE_ID_MATCH_DEVICE,
0298 .idVendor = 0x04DD,
0299 .idProduct = 0x8007,
0300 ZAURUS_MASTER_INTERFACE,
0301 .driver_info = ZAURUS_PXA_INFO,
0302 }, {
0303 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0304 | USB_DEVICE_ID_MATCH_DEVICE,
0305 .idVendor = 0x04DD,
0306 .idProduct = 0x9031,
0307 ZAURUS_MASTER_INTERFACE,
0308 .driver_info = ZAURUS_PXA_INFO,
0309 }, {
0310
0311 USB_DEVICE_AND_INTERFACE_INFO(0x04DD, 0x9031, USB_CLASS_COMM,
0312 USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
0313 .driver_info = (unsigned long) &bogus_mdlm_info,
0314 }, {
0315 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0316 | USB_DEVICE_ID_MATCH_DEVICE,
0317 .idVendor = 0x04DD,
0318 .idProduct = 0x9032,
0319 ZAURUS_MASTER_INTERFACE,
0320 .driver_info = ZAURUS_PXA_INFO,
0321 }, {
0322 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0323 | USB_DEVICE_ID_MATCH_DEVICE,
0324 .idVendor = 0x04DD,
0325 .idProduct = 0x9032,
0326 ZAURUS_FAKE_INTERFACE,
0327 .driver_info = (unsigned long)&bogus_mdlm_info,
0328 }, {
0329 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0330 | USB_DEVICE_ID_MATCH_DEVICE,
0331 .idVendor = 0x04DD,
0332
0333 .idProduct = 0x9050,
0334 ZAURUS_MASTER_INTERFACE,
0335 .driver_info = ZAURUS_PXA_INFO,
0336 },
0337 {
0338
0339 USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
0340 USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
0341 .driver_info = (unsigned long) &bogus_mdlm_info,
0342 }, {
0343
0344 USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
0345 USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
0346 .driver_info = (unsigned long) &bogus_mdlm_info,
0347 },
0348
0349
0350
0351
0352 {
0353 .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
0354 | USB_DEVICE_ID_MATCH_DEVICE,
0355 .idVendor = 0x07B4,
0356 .idProduct = 0x0F02,
0357 ZAURUS_MASTER_INTERFACE,
0358 .driver_info = OLYMPUS_MXL_INFO,
0359 },
0360
0361
0362 {
0363 USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM,
0364 USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
0365 .driver_info = (unsigned long) &bogus_mdlm_info,
0366 },
0367 { },
0368 };
0369 MODULE_DEVICE_TABLE(usb, products);
0370
0371 static struct usb_driver zaurus_driver = {
0372 .name = "zaurus",
0373 .id_table = products,
0374 .probe = usbnet_probe,
0375 .disconnect = usbnet_disconnect,
0376 .suspend = usbnet_suspend,
0377 .resume = usbnet_resume,
0378 .disable_hub_initiated_lpm = 1,
0379 };
0380
0381 module_usb_driver(zaurus_driver);
0382
0383 MODULE_AUTHOR("Pavel Machek, David Brownell");
0384 MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
0385 MODULE_LICENSE("GPL");