USB Hid driver Help

Lucas Tanure tanure at linux.com
Tue Feb 4 08:27:26 EST 2020


On Mon, Feb 3, 2020 at 10:00 PM Lucas Tanure <tanure at linux.com> wrote:
>
> On Mon, Feb 3, 2020 at 8:11 PM Greg KH <greg at kroah.com> wrote:
> >
> > On Mon, Feb 03, 2020 at 04:32:46PM +0000, Lucas Tanure wrote:
> > > Hi,
> > >
> > > I'm trying to write a Hid driver for MCP2210.
> >
> > What type of device is this?
> It is a USB <-> SPI converter.
>
> >
> > > But the USB Hid specification is quite complicated.
> >
> > The kernel should do it "all for you" already, why do you need to create
> > a custom HID driver for this device?
> I need a driver that register an SPI controller with in the kernel.
> So this SPI controller would receive regmap reads/writes and translate
> to USB HID packages and send to the SPI device attached in the other
> side of the cable.
>
> >
> > What type of HID reports does the device export and why doesn't the
> > existing kernel drivers work for you?
> I don't know enough yet to answer about HID Reports, but at end of
> this e-mail I attached the lsub -v of the device.
> I want to use this device in kernel space, registering a SPI
> controller. And with this SPI controller another SPI slave device will
> be registered.
> So, for the SPI slave device it will be like there is no USB in
> between itself and the kernel.
>
> >
> > > I would like to know how to send and receive data to the device. Any
> > > links to a good tutorial ?
> >
> > HID has the idea of "reports" and data comes in and out in that specific
> > format, all depending on how the device describes itself.  There's isn't
> > usually a normal "send/receive" type of thing, but it all depends on the
> > type of device.
> Ok. Reading the datasheet of this device I need to send some 64 byte
> arrays to configure the SPI bus.
> And after that I start to send reports to communicate with the SPI slave device.
>
> >
> > > This is my current driver is attached.
> > >
> > > Thanks
> > > Lucas
> >
> > > #define DEBUG
> > > #include <linux/module.h>
> > > #include <linux/hid.h>
> > > #include <linux/usb.h>
> > >
> > > static int mcp2210_probe(struct hid_device *hdev,
> > >                        const struct hid_device_id *id)
> > > {
> > >       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
> > >       int ret = 0;
> > >
> > >       hid_dbg(hdev, "%s\n", __FUNCTION__);
> > >
> > >       ret = hid_parse(hdev);
> > >       if (ret) {
> > >               hid_err(hdev, "parse failed\n");
> > >               return ret;
> > >       } else {
> > >               hid_dbg(hdev, "parse success\n");
> > >       }
> > >
> > >       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > >       if (ret) {
> > >               hid_err(hdev, "hw start failed\n");
> > >               return ret;
> > >       } else {
> > >               hid_dbg(hdev, "start success\n");
> > >       }
> >
> > Does this all work?
> For this version, it`s takes precedence from HID generic driver, wich is great.
>
> >
> > What fails?
> If I try to execute small test of data communcation:
>
> u8 *buf = kzalloc (64, GFP_KERNEL);
> buf[0] = 0x50; //read EEPROM command
> buf[1] = 0x03 ; // Address to read
>
> ret = hid_hw_raw_request(hdev, 0, buf, 64, HID_INPUT_REPORT, HID_REQ_GET_REPORT)
> ret is -EPIPE.
>
> >
> > thanks,
> >
> > greg k-h
>
> Many Thanks
> Lucas
>
> Bus 001 Device 008: ID 04d8:00de Microchip Technology, Inc. MCP2210
> USB to SPI Master
> Couldn't open device, some information will be missing
> Device Descriptor:
>  bLength                18
>  bDescriptorType         1
>  bcdUSB               2.00
>  bDeviceClass            0
>  bDeviceSubClass         0
>  bDeviceProtocol         0
>  bMaxPacketSize0         8
>  idVendor           0x04d8 Microchip Technology, Inc.
>  idProduct          0x00de
>  bcdDevice            0.02
>  iManufacturer           1
>  iProduct                2
>  iSerial                 3
>  bNumConfigurations      1
>  Configuration Descriptor:
>    bLength                 9
>    bDescriptorType         2
>    wTotalLength       0x0029
>    bNumInterfaces          1
>    bConfigurationValue     1
>    iConfiguration          0
>    bmAttributes         0x80
>      (Bus Powered)
>    MaxPower              100mA
>    Interface Descriptor:
>      bLength                 9
>      bDescriptorType         4
>      bInterfaceNumber        0
>      bAlternateSetting       0
>      bNumEndpoints           2
>      bInterfaceClass         3 Human Interface Device
>      bInterfaceSubClass      0
>      bInterfaceProtocol      0
>      iInterface              0
>        HID Device Descriptor:
>          bLength                 9
>          bDescriptorType        33
>          bcdHID               1.11
>          bCountryCode            0 Not supported
>          bNumDescriptors         1
>          bDescriptorType        34 Report
>          wDescriptorLength      29
>         Report Descriptors:
>           ** UNAVAILABLE **
>      Endpoint Descriptor:
>        bLength                 7
>        bDescriptorType         5
>        bEndpointAddress     0x81  EP 1 IN
>        bmAttributes            3
>          Transfer Type            Interrupt
>          Synch Type               None
>          Usage Type               Data
>        wMaxPacketSize     0x0040  1x 64 bytes
>        bInterval               1
>      Endpoint Descriptor:
>        bLength                 7
>        bDescriptorType         5
>        bEndpointAddress     0x01  EP 1 OUT
>        bmAttributes            3
>          Transfer Type            Interrupt
>          Synch Type               None
>          Usage Type               Data
>        wMaxPacketSize     0x0040  1x 64 bytes
>        bInterval               1

Hi,

If I use hid_hw_output_report I can write my 64 bytes buffer to the device.
And I would expect a 64 bytes answer from the device, but I don't know
how to get it.

How do I know where my output data is going to ? Control Pipe or
Interrupt Pipe ?
How to I get the answer data from the device ?

Thanks
Lucas

static int mcp2210_probe(struct hid_device *hdev,
                         const struct hid_device_id *id)
{
        //struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
        int ret = 0;
        //struct hid_report *report = kzalloc(sizeof(struct
hid_report), GFP_KERNEL);
        u8 *buf = kzalloc(64, GFP_KERNEL);
        u8 *buf2 = kzalloc(64, GFP_KERNEL);

        hid_dbg(hdev, "%s\n", __FUNCTION__);

        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "parse failed\n");
                return ret;
        } else {
                hid_dbg(hdev, "parse success\n");
        }

        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret) {
                hid_err(hdev, "hw start failed\n");
                return ret;
        } else {
                hid_dbg(hdev, "start success\n");
        }
        ret = hid_hw_open(hdev);
        hid_dbg(hdev, "hid_hw_open %d\n", ret);

        buf[0] = 0x50;
        buf[1] = 0x07;
        ret = hid_hw_output_report(hdev, buf, 64);
        hid_dbg(hdev, "hid_hw_output_report %d back
[%x][%x][%x][%x]\n", ret, buf[0], buf[1], buf[2], buf[3]);
        //dmesg prints ret 0

        ret = hid_hw_raw_request(hdev, 0x81, buf2, 64,
HID_INPUT_REPORT, HID_REQ_SET_REPORT);
        hid_dbg(hdev, "hid_input_report %d back [%x][%x][%x][%x]\n",
ret, buf2[0], buf2[1], buf2[2], buf2[3]);
        //dmesg prints ret -32

        kfree(buf);
        kfree(buf2);

        return 0;
}

Dmesg:
[   72.991830] MCP2210 USB SPI Driver 0003:04D8:00DE.0002: mcp2210_probe
[   73.001793] MCP2210 USB SPI Driver 0003:04D8:00DE.0002: parse success
[   73.020234] MCP2210 USB SPI Driver 0003:04D8:00DE.0002:
hiddev96,hidraw0: USB HID v1.11 Device [Microchip Technology Inc.
MCP2210 USB-to-SPI Master] on usb-3f980000.usb-1.3/input0
[   73.039798] MCP2210 USB SPI Driver 0003:04D8:00DE.0002: start success
[   73.111858] MCP2210 USB SPI Driver 0003:04D8:00DE.0002: hid_hw_open 0
[   73.126599] MCP2210 USB SPI Driver 0003:04D8:00DE.0002:
hid_hw_output_report 64 back [50][7][0][0]
[   73.140170] MCP2210 USB SPI Driver 0003:04D8:00DE.0002:
hid_input_report -32 back [81][0][0][0]



More information about the Kernelnewbies mailing list