1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Driver for RobotFuzz OSIF 4 * 5 * Copyright (c) 2013 Andrew Lunn <andrew@lunn.ch> 6 * Copyright (c) 2007 Barry Carter <Barry.Carter@robotfuzz.com> 7 * 8 * Based on the i2c-tiny-usb by 9 * 10 * Copyright (C) 2006 Til Harbaum (Till@Harbaum.org) 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/errno.h> 16 #include <linux/i2c.h> 17 #include <linux/slab.h> 18 #include <linux/usb.h> 19 20 #define OSIFI2C_READ 20 21 #define OSIFI2C_WRITE 21 22 #define OSIFI2C_STOP 22 23 #define OSIFI2C_STATUS 23 24 #define OSIFI2C_SET_BIT_RATE 24 25 26 #define STATUS_ADDRESS_ACK 0 27 #define STATUS_ADDRESS_NAK 2 28 29 struct osif_priv { 30 struct usb_device *usb_dev; 31 struct usb_interface *interface; 32 struct i2c_adapter adapter; 33 unsigned char status; 34 }; 35 36 static int osif_usb_read(struct i2c_adapter *adapter, int cmd, 37 int value, int index, void *data, int len) 38 { 39 struct osif_priv *priv = adapter->algo_data; 40 41 return usb_control_msg(priv->usb_dev, usb_rcvctrlpipe(priv->usb_dev, 0), 42 cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | 43 USB_DIR_IN, value, index, data, len, 2000); 44 } 45 46 static int osif_usb_write(struct i2c_adapter *adapter, int cmd, 47 int value, int index, void *data, int len) 48 { 49 50 struct osif_priv *priv = adapter->algo_data; 51 52 return usb_control_msg(priv->usb_dev, usb_sndctrlpipe(priv->usb_dev, 0), 53 cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 54 value, index, data, len, 2000); 55 } 56 57 static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, 58 int num) 59 { 60 struct osif_priv *priv = adapter->algo_data; 61 struct i2c_msg *pmsg; 62 int ret; 63 int i; 64 65 for (i = 0; i < num; i++) { 66 pmsg = &msgs[i]; 67 68 if (pmsg->flags & I2C_M_RD) { 69 ret = osif_usb_read(adapter, OSIFI2C_READ, 70 pmsg->flags, pmsg->addr, 71 pmsg->buf, pmsg->len); 72 if (ret != pmsg->len) { 73 dev_err(&adapter->dev, "failure reading data\n"); 74 return -EREMOTEIO; 75 } 76 } else { 77 ret = osif_usb_write(adapter, OSIFI2C_WRITE, 78 pmsg->flags, pmsg->addr, 79 pmsg->buf, pmsg->len); 80 if (ret != pmsg->len) { 81 dev_err(&adapter->dev, "failure writing data\n"); 82 return -EREMOTEIO; 83 } 84 } 85 86 ret = osif_usb_read(adapter, OSIFI2C_STOP, 0, 0, NULL, 0); 87 if (ret) { 88 dev_err(&adapter->dev, "failure sending STOP\n"); 89 return -EREMOTEIO; 90 } 91 92 /* read status */ 93 ret = osif_usb_read(adapter, OSIFI2C_STATUS, 0, 0, 94 &priv->status, 1); 95 if (ret != 1) { 96 dev_err(&adapter->dev, "failure reading status\n"); 97 return -EREMOTEIO; 98 } 99 100 if (priv->status != STATUS_ADDRESS_ACK) { 101 dev_dbg(&adapter->dev, "status = %d\n", priv->status); 102 return -EREMOTEIO; 103 } 104 } 105 106 return i; 107 } 108 109 static u32 osif_func(struct i2c_adapter *adapter) 110 { 111 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 112 } 113 114 static const struct i2c_algorithm osif_algorithm = { 115 .master_xfer = osif_xfer, 116 .functionality = osif_func, 117 }; 118 119 #define USB_OSIF_VENDOR_ID 0x1964 120 #define USB_OSIF_PRODUCT_ID 0x0001 121 122 static const struct usb_device_id osif_table[] = { 123 { USB_DEVICE(USB_OSIF_VENDOR_ID, USB_OSIF_PRODUCT_ID) }, 124 { } 125 }; 126 MODULE_DEVICE_TABLE(usb, osif_table); 127 128 static int osif_probe(struct usb_interface *interface, 129 const struct usb_device_id *id) 130 { 131 int ret; 132 struct osif_priv *priv; 133 u16 version; 134 135 priv = devm_kzalloc(&interface->dev, sizeof(*priv), GFP_KERNEL); 136 if (!priv) 137 return -ENOMEM; 138 139 priv->usb_dev = usb_get_dev(interface_to_usbdev(interface)); 140 priv->interface = interface; 141 142 usb_set_intfdata(interface, priv); 143 144 priv->adapter.owner = THIS_MODULE; 145 priv->adapter.class = I2C_CLASS_HWMON; 146 priv->adapter.algo = &osif_algorithm; 147 priv->adapter.algo_data = priv; 148 snprintf(priv->adapter.name, sizeof(priv->adapter.name), 149 "OSIF at bus %03d device %03d", 150 priv->usb_dev->bus->busnum, priv->usb_dev->devnum); 151 152 /* 153 * Set bus frequency. The frequency is: 154 * 120,000,000 / ( 16 + 2 * div * 4^prescale). 155 * Using dev = 52, prescale = 0 give 100KHz */ 156 ret = osif_usb_read(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0, 157 NULL, 0); 158 if (ret) { 159 dev_err(&interface->dev, "failure sending bit rate"); 160 usb_put_dev(priv->usb_dev); 161 return ret; 162 } 163 164 i2c_add_adapter(&(priv->adapter)); 165 166 version = le16_to_cpu(priv->usb_dev->descriptor.bcdDevice); 167 dev_info(&interface->dev, 168 "version %x.%02x found at bus %03d address %03d", 169 version >> 8, version & 0xff, 170 priv->usb_dev->bus->busnum, priv->usb_dev->devnum); 171 172 return 0; 173 } 174 175 static void osif_disconnect(struct usb_interface *interface) 176 { 177 struct osif_priv *priv = usb_get_intfdata(interface); 178 179 i2c_del_adapter(&(priv->adapter)); 180 usb_set_intfdata(interface, NULL); 181 usb_put_dev(priv->usb_dev); 182 } 183 184 static struct usb_driver osif_driver = { 185 .name = "RobotFuzz Open Source InterFace, OSIF", 186 .probe = osif_probe, 187 .disconnect = osif_disconnect, 188 .id_table = osif_table, 189 }; 190 191 module_usb_driver(osif_driver); 192 193 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); 194 MODULE_AUTHOR("Barry Carter <barry.carter@robotfuzz.com>"); 195 MODULE_DESCRIPTION("RobotFuzz OSIF driver"); 196 MODULE_LICENSE("GPL v2"); 197