On Thu, Mar 31, 2022 at 09:33:04PM -0500, frank zago wrote: > The CH341 is a multifunction chip, presenting 3 different USB PID. One > of these functions is for I2C/SPI/GPIO. This new set of drivers will > manage I2C and GPIO. > > Signed-off-by: frank zago <frank@xxxxxxxx> > --- > +static int ch341_usb_probe(struct usb_interface *iface, > + const struct usb_device_id *usb_id) > +{ > + struct usb_host_endpoint *endpoints; > + struct ch341_device *dev; > + int rc; > + > + dev = devm_kzalloc(&iface->dev, sizeof(*dev), GFP_KERNEL); > + if (!dev) > + return -ENOMEM; > + > + dev->usb_dev = usb_get_dev(interface_to_usbdev(iface)); No need to grab a reference unless you're going to hold on to it past disconnect(). > + dev->iface = iface; > + mutex_init(&dev->usb_lock); > + > + if (iface->cur_altsetting->desc.bNumEndpoints != 3) { > + rc = -ENODEV; > + goto free_dev; > + } > + > + endpoints = iface->cur_altsetting->endpoint; > + if (!usb_endpoint_is_bulk_in(&endpoints[0].desc) || > + !usb_endpoint_is_bulk_out(&endpoints[1].desc) || > + !usb_endpoint_xfer_int(&endpoints[2].desc)) { > + rc = -ENODEV; > + goto free_dev; > + } Please use usb_find_common_endpoints() for the above. > + > + dev->ep_in = endpoints[0].desc.bEndpointAddress; > + dev->ep_out = endpoints[1].desc.bEndpointAddress; > + dev->ep_intr = endpoints[2].desc.bEndpointAddress; > + dev->ep_intr_interval = endpoints[2].desc.bInterval; > + > + usb_set_intfdata(iface, dev); > + > + rc = mfd_add_hotplug_devices(&iface->dev, ch341_devs, > + ARRAY_SIZE(ch341_devs)); > + if (rc) { > + rc = dev_err_probe(&iface->dev, rc, > + "Failed to add mfd devices to core\n"); > + goto free_dev; > + } > + > + return 0; > + > +free_dev: > + usb_put_dev(dev->usb_dev); > + > + return rc; > +} > + > +static void ch341_usb_disconnect(struct usb_interface *usb_if) > +{ > + struct ch341_device *dev = usb_get_intfdata(usb_if); > + > + mfd_remove_devices(&usb_if->dev); > + usb_put_dev(dev->usb_dev); > +} Johan