From: Tim Sander <tim@krieglstein.org>
To: "Alex Bennée" <alex.bennee@linaro.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
qemu-devel@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [Qemu-devel] [PATCH RFC] i2c-tiny-usb
Date: Fri, 27 Nov 2015 09:41:35 +0100 [thread overview]
Message-ID: <1727507.5NJ00yyck5@dabox> (raw)
In-Reply-To: <87si3sbpnc.fsf@linaro.org>
Hi Alex
Thanks for your feedback, answers as usual inline.
Am Donnerstag, 26. November 2015, 18:07:35 schrieb Alex Bennée:
> Tim Sander <tim@krieglstein.org> writes:
> > Hi
> >
> > Below is a patch implementing the i2c-tiny-usb device.
> > I am currently not sure about the i2c semantics. I think
> > incrementing the address on longer reads is wrong?
> > But at least i can read the high byte(?) of the temperature
> > via "i2cget -y 0 0x50".
> >
> > With this device it should be possible to define i2c busses
> > via command line e.g:
> > -device usb-i2c-tiny,id=i2c-0 -device tmp105,bus=i2c,address=0x50
> > have been used for the first test.
>
> You are missing a s-o-b line and scripts/checkpatch.pl complains about a
> few things you should fix before your next submission.
I was unsure about the access length so i was just asking for feedback this
time, thats why omitted the signed of by line.
It seems as if i grabbed an older version of checkpatch as these errors didn't
come up with the slightly older script. These new occurences will be fixed.
> > Best regards
> > Tim
> > ---
> >
> > default-configs/usb.mak | 1 +
> > hw/usb/Makefile.objs | 1 +
> > hw/usb/dev-i2c-tiny.c | 383
> > ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 385
> > insertions(+)
> > create mode 100644 hw/usb/dev-i2c-tiny.c
> >
> > diff --git a/default-configs/usb.mak b/default-configs/usb.mak
> > index f4b8568..01d2c9f 100644
> > --- a/default-configs/usb.mak
> > +++ b/default-configs/usb.mak
> > @@ -8,3 +8,4 @@ CONFIG_USB_AUDIO=y
> >
> > CONFIG_USB_SERIAL=y
> > CONFIG_USB_NETWORK=y
> > CONFIG_USB_BLUETOOTH=y
> >
> > +CONFIG_USB_I2C_TINY=y
> > diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
> > index 8f00fbd..3a4c337 100644
> > --- a/hw/usb/Makefile.objs
> > +++ b/hw/usb/Makefile.objs
> > @@ -20,6 +20,7 @@ common-obj-$(CONFIG_USB_AUDIO) += dev-audio.o
> >
> > common-obj-$(CONFIG_USB_SERIAL) += dev-serial.o
> > common-obj-$(CONFIG_USB_NETWORK) += dev-network.o
> > common-obj-$(CONFIG_USB_BLUETOOTH) += dev-bluetooth.o
> >
> > +common-obj-$(CONFIG_USB_I2C_TINY) += dev-i2c-tiny.o
> >
> > ifeq ($(CONFIG_USB_SMARTCARD),y)
> > common-obj-y += dev-smartcard-reader.o
> >
> > diff --git a/hw/usb/dev-i2c-tiny.c b/hw/usb/dev-i2c-tiny.c
> > new file mode 100644
> > index 0000000..1dabb36
> > --- /dev/null
> > +++ b/hw/usb/dev-i2c-tiny.c
> > @@ -0,0 +1,383 @@
> > +/*
> > + * I2C tiny usb device emulation
> > + *
> > + * Copyright (c) 2015 Tim Sander <tim@krieglstein.org>
> > + *
> > + * Loosly based on usb dev-serial.c:
> > + * Copyright (c) 2006 CodeSourcery.
> > + * Copyright (c) 2008 Samuel Thibault <samuel.thibault@ens-lyon.org>
> > + * Written by Paul Brook, reused for FTDI by Samuel Thibault
> > + *
> > + * This code is licensed under the LGPL.
> > + *
> > + */
> > +
> > +#include "qemu-common.h"
> > +#include "qemu/error-report.h"
> > +#include "hw/usb.h"
> > +#include "hw/usb/desc.h"
> > +#include "hw/i2c/i2c.h"
> > +#include "sysemu/char.h"
> > +#include "endian.h"
> > +
> > +/* #define DEBUG_USBI2C */
> > +
> > +#ifdef DEBUG_USBI2C
> > +#define DPRINTF(fmt, ...) \
> > +do { printf("usb-i2c-tiny: " fmt , ## __VA_ARGS__); } while (0)
> > +#else
> > +#define DPRINTF(fmt, ...) do {} while (0)
> > +#endif
> > +
> > +/* commands from USB, must e.g. match command ids in kernel driver */
> > +#define CMD_ECHO 0
> > +#define CMD_GET_FUNC 1
> > +#define CMD_SET_DELAY 2
> > +#define CMD_GET_STATUS 3
> > +
> > +/* To determine what functionality is present */
> > +#define I2C_FUNC_I2C 0x00000001
> > +#define I2C_FUNC_10BIT_ADDR 0x00000002
> > +#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004
> > +#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0
> > */
> > +#define I2C_FUNC_SMBUS_QUICK 0x00010000
> > +#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
> > +#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
> > +#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
> > +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
> > +#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
> > +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
> > +#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
> > +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
> > +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
> > +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /*I2C-like
> > blk-xfr */ +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000
> > /*1-byte reg. addr.*/ +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2
> > 0x10000000 /*I2C-like blk-xfer*/ +#define
> > I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte regadr*/
> > +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0
> > */ +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus
> > 2.0 */ +
> > +#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
> > + I2C_FUNC_SMBUS_WRITE_BYTE)
> > +#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
> > + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
> > +#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
> > + I2C_FUNC_SMBUS_WRITE_WORD_DATA)
> > +#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
> > + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
> > +#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
> > + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
> > +
> > +#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
> > + I2C_FUNC_SMBUS_BYTE | \
> > + I2C_FUNC_SMBUS_BYTE_DATA | \
> > + I2C_FUNC_SMBUS_WORD_DATA | \
> > + I2C_FUNC_SMBUS_PROC_CALL | \
> > + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
> > + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
> > + I2C_FUNC_SMBUS_I2C_BLOCK)
> > +
> > +#define DeviceOutVendor
> > ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) +#define
> > DeviceInVendor ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) +
> > +typedef struct {
> > + USBDevice dev;
> > + I2CBus *i2cbus;
> > +} UsbI2cTinyState;
> > +
> > +#define TYPE_USB_I2C_TINY "usb-i2c-dev"
> > +#define USB_I2C_TINY_DEV(obj) OBJECT_CHECK(UsbI2cTinyState, \
> > + (obj), TYPE_USB_I2C_TINY)
> > +
> > +enum {
> > + STR_MANUFACTURER = 1,
> > + STR_PRODUCT_SERIAL,
> > + STR_SERIALNUMBER,
> > +};
> > +
> > +static const USBDescStrings desc_strings = {
> > + [STR_MANUFACTURER] = "QEMU",
> > + [STR_PRODUCT_SERIAL] = "QEMU USB I2C Tiny",
> > + [STR_SERIALNUMBER] = "1",
> > +};
> > +
> > +static const USBDescIface desc_iface0 = {
> > + .bInterfaceNumber = 1,
> > + .bNumEndpoints = 0,
> > + .bInterfaceClass = 0xff,
> > + .bInterfaceSubClass = 0xff,
> > + .bInterfaceProtocol = 0xff,
> > + .eps = (USBDescEndpoint[]) {
> > + }
> > +};
> > +
> > +static const USBDescDevice desc_device = {
> > + .bcdUSB = 0x0110,
> > + .bMaxPacketSize0 = 8,
> > + .bNumConfigurations = 1,
> > + .confs = (USBDescConfig[]) {
> > + {
> > + .bNumInterfaces = 1,
> > + .bConfigurationValue = 1,
> > + .bmAttributes = USB_CFG_ATT_ONE,
> > + .bMaxPower = 50,
> > + .nif = 1,
> > + .ifs = &desc_iface0,
> > + },
> > + },
> > +};
> > +
> > +static const USBDesc desc_usb_i2c = {
> > + .id = {
> > + .idVendor = 0x0403,
> > + .idProduct = 0xc631,
> > + .bcdDevice = 0x0205,
>
> Where did these magic numbers come from?
I guess i have forgotton to add the link of the hardware which i am
aiming to emulate:
http://www.harbaum.org/till/i2c_tiny_usb/index.shtml
Looking at the Linux driver it seems there are two supported manufacturer
numbers, i just took one of them.
> > + .iManufacturer = STR_MANUFACTURER,
> > + .iProduct = STR_PRODUCT_SERIAL,
> > + .iSerialNumber = STR_SERIALNUMBER,
> > + },
> > + .full = &desc_device,
> > + .str = desc_strings,
> > +};
> > +
> > +static int usb_i2c_read_byte(I2CBus *bus, uint8_t addr)
> > +{
> > + int retval;
> > + i2c_start_transfer(bus, addr, 1);
> > + retval = i2c_recv(bus);
> > + i2c_end_transfer(bus);
> > + return retval;
> > +}
> > +
> > +static int usb_i2c_write_byte(I2CBus *bus, uint8_t addr, uint8_t data)
> > +{
> > + int retval;
> > + i2c_start_transfer(bus, addr, 0);
> > + retval = i2c_send(bus, data);
> > + i2c_end_transfer(bus);
> > + return retval;
> > +}
> > +
> > +static void usb_i2c_handle_reset(USBDevice *dev)
> > +{
> > + DPRINTF("reset\n");
> > +}
> > +
> > +static void usb_i2c_handle_control(USBDevice *dev, USBPacket *p,
> > + int request, int value, int index, int length, uint8_t
> > *data) +{
> > + UsbI2cTinyState *s = (UsbI2cTinyState *)dev;
> > + int ret;
> > +
> > + DPRINTF("got control %x, value %x\n", request, value);
> > + DPRINTF("iov_base:%lx pid:%x stream:%x param:%lx status:%x len:%x\n",
> > + (uint64_t)(p->iov).iov->iov_base, p->pid, p->stream,
> > p->parameter, + p->status, p->actual_length);
> > + ret = usb_desc_handle_control(dev, p, request, value, index, length,
> > data); + DPRINTF("usb_desc_handle_control return value: %i status:
> > %x\n", ret, + p->status);
>
> I get that debug output is useful for debugging but if you want to
> maintain ability to look at the i2c transactions you might want to
> consider the tracing infrastructure.
Any pointers a quick search turned up the
http://wiki.qemu.org/Features/Tracing/Roadmap page but this seems pretty
outdated?
> > + if (ret >= 0) {
> > + return;
> > + }
> > +
> > + switch (request) {
> > + case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
> > + break;
> > +
>
> Again where are these magic numbers coming from?
I choose this usb device as it has a mainline driver and is reasonable simple.
These numbers are just what i have seen during reverse engineering: starting
up the linux i2c-tiny-usb module and look for the results. So i don't know
more than what i have written into the comments.
<snip>
Best regards
Tim
next prev parent reply other threads:[~2015-11-27 8:42 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-26 16:35 [Qemu-devel] [PATCH RFC] i2c-tiny-usb Tim Sander
2015-11-26 18:07 ` Alex Bennée
2015-11-27 8:41 ` Tim Sander [this message]
2015-11-27 9:35 ` Markus Armbruster
2015-11-27 11:57 ` Alex Bennée
2015-11-27 6:48 ` Gerd Hoffmann
2015-11-27 10:59 ` Tim Sander
[not found] ` <56582329.5040304@redhat.com>
2015-11-27 12:39 ` Tim Sander
2015-11-27 12:53 ` Paolo Bonzini
2015-12-09 16:40 ` [Qemu-devel] i2c data address question was " Tim Sander
2015-12-09 17:04 ` Paolo Bonzini
2015-12-16 15:56 ` [Qemu-devel] [PATCH] i2c-tiny-usb: add new usb to i2c bridge Tim Sander
2015-12-17 16:15 ` Gerd Hoffmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1727507.5NJ00yyck5@dabox \
--to=tim@krieglstein.org \
--cc=alex.bennee@linaro.org \
--cc=kraxel@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.