/* Structure to hold all of our device specific stuff */ struct i2c_diolan_u2c {
u8 obuffer[DIOLAN_OUTBUF_LEN]; /* output buffer */
u8 ibuffer[DIOLAN_INBUF_LEN]; /* input buffer */ int ep_in, ep_out; /* Endpoints */ struct usb_device *usb_dev; /* the usb device for this device */ struct usb_interface *interface;/* the interface for this device */ struct i2c_adapter adapter; /* i2c related things */ int olen; /* Output buffer length */ int ocount; /* Number of enqueued messages */
};
static uint frequency = I2C_MAX_STANDARD_MODE_FREQ; /* I2C clock frequency in Hz */
module_param(frequency, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz");
/* usb layer */
/* Send command to device, and get response. */ staticint diolan_usb_transfer(struct i2c_diolan_u2c *dev)
{ int ret = 0; int actual; int i;
if (!dev->olen || !dev->ocount) return -EINVAL;
ret = usb_bulk_msg(dev->usb_dev,
usb_sndbulkpipe(dev->usb_dev, dev->ep_out),
dev->obuffer, dev->olen, &actual,
DIOLAN_USB_TIMEOUT); if (!ret) { for (i = 0; i < dev->ocount; i++) { int tmpret;
tmpret = usb_bulk_msg(dev->usb_dev,
usb_rcvbulkpipe(dev->usb_dev,
dev->ep_in),
dev->ibuffer, sizeof(dev->ibuffer), &actual,
DIOLAN_USB_TIMEOUT); /* * Stop command processing if a previous command * returned an error. * Note that we still need to retrieve all messages.
*/ if (ret < 0) continue;
ret = tmpret; if (ret == 0 && actual > 0) { switch (dev->ibuffer[actual - 1]) { case RESP_NACK: /* * Return ENXIO if NACK was received as * response to the address phase, * EIO otherwise
*/
ret = i == 1 ? -ENXIO : -EIO; break; case RESP_TIMEOUT:
ret = -ETIMEDOUT; break; case RESP_OK: /* strip off return code */
ret = actual - 1; break; default:
ret = -EIO; break;
}
}
}
}
dev->olen = 0;
dev->ocount = 0; return ret;
}
/* Send command with one byte of data */ staticint diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data, bool flush)
{
dev->obuffer[dev->olen++] = command;
dev->obuffer[dev->olen++] = data;
dev->ocount++; return diolan_write_cmd(dev, flush);
}
/* Send command with two bytes of data */ staticint diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1,
u8 d2, bool flush)
{
dev->obuffer[dev->olen++] = command;
dev->obuffer[dev->olen++] = d1;
dev->obuffer[dev->olen++] = d2;
dev->ocount++; return diolan_write_cmd(dev, flush);
}
/* * Flush input queue. * If we don't do this at startup and the controller has queued up * messages which were not retrieved, it will stop responding * at some point.
*/ staticvoid diolan_flush_input(struct i2c_diolan_u2c *dev)
{ int i;
for (i = 0; i < 10; i++) { int actual = 0; int ret;
ret = usb_bulk_msg(dev->usb_dev,
usb_rcvbulkpipe(dev->usb_dev, dev->ep_in),
dev->ibuffer, sizeof(dev->ibuffer), &actual,
DIOLAN_USB_TIMEOUT); if (ret < 0 || actual == 0) break;
} if (i == 10)
dev_err(&dev->interface->dev, "Failed to flush input buffer\n");
}
staticvoid diolan_fw_version(struct i2c_diolan_u2c *dev)
{ int ret;
ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true); if (ret >= 2)
dev_info(&dev->interface->dev, "Diolan U2C firmware version %u.%u\n",
(unsignedint)dev->ibuffer[0],
(unsignedint)dev->ibuffer[1]);
}
staticvoid diolan_get_serial(struct i2c_diolan_u2c *dev)
{ int ret;
u32 serial;
ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true); if (ret >= 4) {
serial = le32_to_cpu(*(u32 *)dev->ibuffer);
dev_info(&dev->interface->dev, "Diolan U2C serial number %u\n", serial);
}
}
staticint diolan_init(struct i2c_diolan_u2c *dev)
{ int speed, ret;
if (frequency >= 2 * I2C_MAX_STANDARD_MODE_FREQ) {
speed = U2C_I2C_SPEED_FAST;
frequency = I2C_MAX_FAST_MODE_FREQ;
} elseif (frequency >= I2C_MAX_STANDARD_MODE_FREQ || frequency == 0) {
speed = U2C_I2C_SPEED_STD;
frequency = I2C_MAX_STANDARD_MODE_FREQ;
} else {
speed = U2C_I2C_SPEED(frequency); if (speed > U2C_I2C_SPEED_2KHZ)
speed = U2C_I2C_SPEED_2KHZ;
frequency = U2C_I2C_FREQ(speed);
}
dev_info(&dev->interface->dev, "Diolan U2C at USB bus %03d address %03d speed %d Hz\n",
dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency);
if (hostif->desc.bInterfaceNumber != 0
|| hostif->desc.bNumEndpoints < 2) return -ENODEV;
/* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) {
ret = -ENOMEM; goto error;
}
dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.