18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PL-2301/2302 USB host-to-host link cables 48c2ecf20Sopenharmony_ci * Copyright (C) 2000-2005 by David Brownell 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci// #define DEBUG // error path messages, extra info 88c2ecf20Sopenharmony_ci// #define VERBOSE // more; success messages 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 128c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 148c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 158c2ecf20Sopenharmony_ci#include <linux/mii.h> 168c2ecf20Sopenharmony_ci#include <linux/usb.h> 178c2ecf20Sopenharmony_ci#include <linux/usb/usbnet.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * Prolific PL-2301/PL-2302 driver ... http://www.prolific.com.tw/ 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * The protocol and handshaking used here should be bug-compatible 248c2ecf20Sopenharmony_ci * with the Linux 2.2 "plusb" driver, by Deti Fliegl. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * HEADS UP: this handshaking isn't all that robust. This driver 278c2ecf20Sopenharmony_ci * gets confused easily if you unplug one end of the cable then 288c2ecf20Sopenharmony_ci * try to connect it again; you'll need to restart both ends. The 298c2ecf20Sopenharmony_ci * "naplink" software (used by some PlayStation/2 developers) does 308c2ecf20Sopenharmony_ci * the handshaking much better! Also, sometimes this hardware 318c2ecf20Sopenharmony_ci * seems to get wedged under load. Prolific docs are weak, and 328c2ecf20Sopenharmony_ci * don't identify differences between PL2301 and PL2302, much less 338c2ecf20Sopenharmony_ci * anything to explain the different PL2302 versions observed. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * NOTE: pl2501 has several modes, including pl2301 and pl2302 368c2ecf20Sopenharmony_ci * compatibility. Some docs suggest the difference between 2301 378c2ecf20Sopenharmony_ci * and 2302 is only to make MS-Windows use a different driver... 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * pl25a1 glue based on patch from Tony Gibbs. Prolific "docs" on 408c2ecf20Sopenharmony_ci * this chip are as usual incomplete about what control messages 418c2ecf20Sopenharmony_ci * are supported. 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * Bits 0-4 can be used for software handshaking; they're set from 468c2ecf20Sopenharmony_ci * one end, cleared from the other, "read" with the interrupt byte. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci#define PL_S_EN (1<<7) /* (feature only) suspend enable */ 498c2ecf20Sopenharmony_ci/* reserved bit -- rx ready (6) ? */ 508c2ecf20Sopenharmony_ci#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */ 518c2ecf20Sopenharmony_ci#define PL_RESET_OUT (1<<4) /* reset output pipe */ 528c2ecf20Sopenharmony_ci#define PL_RESET_IN (1<<3) /* reset input pipe */ 538c2ecf20Sopenharmony_ci#define PL_TX_C (1<<2) /* transmission complete */ 548c2ecf20Sopenharmony_ci#define PL_TX_REQ (1<<1) /* transmission received */ 558c2ecf20Sopenharmony_ci#define PL_PEER_E (1<<0) /* peer exists */ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline int 588c2ecf20Sopenharmony_cipl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE, 618c2ecf20Sopenharmony_ci val, index, NULL, 0); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline int 658c2ecf20Sopenharmony_cipl_clear_QuickLink_features(struct usbnet *dev, int val) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci return pl_vendor_req(dev, 1, (u8) val, 0); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline int 718c2ecf20Sopenharmony_cipl_set_QuickLink_features(struct usbnet *dev, int val) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci return pl_vendor_req(dev, 3, (u8) val, 0); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistatic int pl_reset(struct usbnet *dev) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci int status; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* some units seem to need this reset, others reject it utterly. 818c2ecf20Sopenharmony_ci * FIXME be more like "naplink" or windows drivers. 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci status = pl_set_QuickLink_features(dev, 848c2ecf20Sopenharmony_ci PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); 858c2ecf20Sopenharmony_ci if (status != 0 && netif_msg_probe(dev)) 868c2ecf20Sopenharmony_ci netif_dbg(dev, link, dev->net, "pl_reset --> %d\n", status); 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic const struct driver_info prolific_info = { 918c2ecf20Sopenharmony_ci .description = "Prolific PL-2301/PL-2302/PL-25A1/PL-27A1", 928c2ecf20Sopenharmony_ci .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, 938c2ecf20Sopenharmony_ci /* some PL-2302 versions seem to fail usb_set_interface() */ 948c2ecf20Sopenharmony_ci .reset = pl_reset, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/*-------------------------------------------------------------------------*/ 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * Proilific's name won't normally be on the cables, and 1028c2ecf20Sopenharmony_ci * may not be on the device. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic const struct usb_device_id products [] = { 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* full speed cables */ 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci USB_DEVICE(0x067b, 0x0000), // PL-2301 1108c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1118c2ecf20Sopenharmony_ci}, { 1128c2ecf20Sopenharmony_ci USB_DEVICE(0x067b, 0x0001), // PL-2302 1138c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1148c2ecf20Sopenharmony_ci}, 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* high speed cables */ 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci USB_DEVICE(0x067b, 0x25a1), /* PL-25A1, no eeprom */ 1198c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1208c2ecf20Sopenharmony_ci}, { 1218c2ecf20Sopenharmony_ci USB_DEVICE(0x050d, 0x258a), /* Belkin F5U258/F5U279 (PL-25A1) */ 1228c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1238c2ecf20Sopenharmony_ci}, { 1248c2ecf20Sopenharmony_ci USB_DEVICE(0x3923, 0x7825), /* National Instruments USB 1258c2ecf20Sopenharmony_ci * Host-to-Host Cable 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci}, 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* super speed cables */ 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci USB_DEVICE(0x067b, 0x27a1), /* PL-27A1, no eeprom 1348c2ecf20Sopenharmony_ci * also: goobay Active USB 3.0 1358c2ecf20Sopenharmony_ci * Data Link, 1368c2ecf20Sopenharmony_ci * Unitek Y-3501 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci .driver_info = (unsigned long) &prolific_info, 1398c2ecf20Sopenharmony_ci}, 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci { }, // END 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, products); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic struct usb_driver plusb_driver = { 1468c2ecf20Sopenharmony_ci .name = "plusb", 1478c2ecf20Sopenharmony_ci .id_table = products, 1488c2ecf20Sopenharmony_ci .probe = usbnet_probe, 1498c2ecf20Sopenharmony_ci .disconnect = usbnet_disconnect, 1508c2ecf20Sopenharmony_ci .suspend = usbnet_suspend, 1518c2ecf20Sopenharmony_ci .resume = usbnet_resume, 1528c2ecf20Sopenharmony_ci .disable_hub_initiated_lpm = 1, 1538c2ecf20Sopenharmony_ci}; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cimodule_usb_driver(plusb_driver); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ciMODULE_AUTHOR("David Brownell"); 1588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Prolific PL-2301/2302/25A1/27A1 USB Host to Host Link Driver"); 1598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 160