From 91eef3e2fee581b00f027bbb0d144788a3c609a9 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 21 Jan 2014 21:56:27 +0100 Subject: staging/bluetooth: Add hci_h4p driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add hci_h4p bluetooth driver to staging tree. This device is used for example on Nokia N900 cell phone. Signed-off-by: Pali Rohár Signed-off-by: Pavel Machek Thanks-to: Sebastian Reichel Thanks-to: Joe Perches Signed-off-by: Greg Kroah-Hartman --- include/linux/platform_data/bt-nokia-h4p.h | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 include/linux/platform_data/bt-nokia-h4p.h (limited to 'include') diff --git a/include/linux/platform_data/bt-nokia-h4p.h b/include/linux/platform_data/bt-nokia-h4p.h new file mode 100644 index 000000000000..30d169dfadf3 --- /dev/null +++ b/include/linux/platform_data/bt-nokia-h4p.h @@ -0,0 +1,38 @@ +/* + * This file is part of Nokia H4P bluetooth driver + * + * Copyright (C) 2010 Nokia Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +/** + * struct hci_h4p_platform data - hci_h4p Platform data structure + */ +struct hci_h4p_platform_data { + int chip_type; + int bt_sysclk; + unsigned int bt_wakeup_gpio; + unsigned int host_wakeup_gpio; + unsigned int reset_gpio; + int reset_gpio_shared; + unsigned int uart_irq; + phys_addr_t uart_base; + const char *uart_iclk; + const char *uart_fclk; + void (*set_pm_limits)(struct device *dev, bool set); +}; -- cgit v1.2.3 From b7945b77cd03094458f3624bc82a27e0d36e75d0 Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Thu, 23 Jan 2014 23:12:29 +0200 Subject: staging: usbip: convert usbip-host driver to usb_device_driver This driver was previously an interface driver. Since USB/IP exports a whole device, not just an interface, it would make sense to be a device driver. This patch also modifies the way userspace sees and uses a shared device: * the usbip_status file is no longer created for interface 0, but for the whole device (such as /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1/usbip_status). * per interface information, such as interface class or protocol, is no longer sent/received; only device specific information is transmitted. * since the driver was moved one level below in the USB architecture, there is no need to bind/unbind each interface, just the device as a whole. Signed-off-by: Valentina Manea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub.h | 2 +- drivers/staging/usbip/stub_dev.c | 150 ++++++++------------- drivers/staging/usbip/stub_main.c | 6 +- drivers/staging/usbip/stub_rx.c | 2 +- .../usbip/userspace/libsrc/usbip_host_driver.c | 45 +++---- drivers/staging/usbip/userspace/src/usbip_bind.c | 142 ++++++++----------- drivers/staging/usbip/userspace/src/usbip_list.c | 19 +-- drivers/staging/usbip/userspace/src/usbip_unbind.c | 51 ++----- drivers/staging/usbip/userspace/src/usbipd.c | 15 --- drivers/usb/core/generic.c | 1 + drivers/usb/core/message.c | 1 + include/linux/usb.h | 4 + 12 files changed, 150 insertions(+), 288 deletions(-) (limited to 'include') diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h index a73e437ec215..82e539a4fcff 100644 --- a/drivers/staging/usbip/stub.h +++ b/drivers/staging/usbip/stub.h @@ -93,7 +93,7 @@ struct bus_id_priv { extern struct kmem_cache *stub_priv_cache; /* stub_dev.c */ -extern struct usb_driver stub_driver; +extern struct usb_device_driver stub_driver; /* stub_main.c */ struct bus_id_priv *get_busid_priv(const char *busid); diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index 76a1ff0e6275..b0bfd3430d47 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -279,21 +279,19 @@ static void stub_device_unusable(struct usbip_device *ud) * * Allocates and initializes a new stub_device struct. */ -static struct stub_device *stub_device_alloc(struct usb_device *udev, - struct usb_interface *interface) +static struct stub_device *stub_device_alloc(struct usb_device *udev) { struct stub_device *sdev; - int busnum = interface_to_busnum(interface); - int devnum = interface_to_devnum(interface); + int busnum = udev->bus->busnum; + int devnum = udev->devnum; - dev_dbg(&interface->dev, "allocating stub device"); + dev_dbg(&udev->dev, "allocating stub device"); /* yes, it's a new device */ sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL); if (!sdev) return NULL; - sdev->interface = usb_get_intf(interface); sdev->udev = usb_get_dev(udev); /* @@ -322,7 +320,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev, usbip_start_eh(&sdev->ud); - dev_dbg(&interface->dev, "register new interface\n"); + dev_dbg(&udev->dev, "register new device\n"); return sdev; } @@ -332,32 +330,20 @@ static void stub_device_free(struct stub_device *sdev) kfree(sdev); } -/* - * If a usb device has multiple active interfaces, this driver is bound to all - * the active interfaces. However, usbip exports *a* usb device (i.e., not *an* - * active interface). Currently, a userland program must ensure that it - * looks at the usbip's sysfs entries of only the first active interface. - * - * TODO: use "struct usb_device_driver" to bind a usb device. - * However, it seems it is not fully supported in mainline kernel yet - * (2.6.19.2). - */ -static int stub_probe(struct usb_interface *interface, - const struct usb_device_id *id) +static int stub_probe(struct usb_device *udev) { - struct usb_device *udev = interface_to_usbdev(interface); struct stub_device *sdev = NULL; - const char *udev_busid = dev_name(interface->dev.parent); - int err = 0; + const char *udev_busid = dev_name(&udev->dev); + int err = 0, config; struct bus_id_priv *busid_priv; - dev_dbg(&interface->dev, "Enter\n"); + dev_dbg(&udev->dev, "Enter\n"); /* check we should claim or not by busid_table */ busid_priv = get_busid_priv(udev_busid); if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) || (busid_priv->status == STUB_BUSID_OTHER)) { - dev_info(&interface->dev, + dev_info(&udev->dev, "%s is not in match_busid table... skip!\n", udev_busid); @@ -383,60 +369,36 @@ static int stub_probe(struct usb_interface *interface, return -ENODEV; } - if (busid_priv->status == STUB_BUSID_ALLOC) { - sdev = busid_priv->sdev; - if (!sdev) - return -ENODEV; - - busid_priv->interf_count++; - dev_info(&interface->dev, - "usbip-host: register new interface (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); - - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - - err = stub_add_files(&interface->dev); - if (err) { - dev_err(&interface->dev, "stub_add_files for %s\n", - udev_busid); - usb_set_intfdata(interface, NULL); - busid_priv->interf_count--; - return err; - } - - usb_get_intf(interface); - return 0; - } - /* ok, this is my device */ - sdev = stub_device_alloc(udev, interface); + sdev = stub_device_alloc(udev); if (!sdev) return -ENOMEM; - dev_info(&interface->dev, - "usbip-host: register new device (bus %u dev %u ifn %u)\n", - udev->bus->busnum, udev->devnum, - interface->cur_altsetting->desc.bInterfaceNumber); + dev_info(&udev->dev, + "usbip-host: register new device (bus %u dev %u)\n", + udev->bus->busnum, udev->devnum); - busid_priv->interf_count = 0; busid_priv->shutdown_busid = 0; - /* set private data to usb_interface */ - usb_set_intfdata(interface, sdev); - busid_priv->interf_count++; + config = usb_choose_configuration(udev); + if (config >= 0) { + err = usb_set_configuration(udev, config); + if (err && err != -ENODEV) + dev_err(&udev->dev, "can't set config #%d, error %d\n", + config, err); + } + + /* set private data to usb_device */ + dev_set_drvdata(&udev->dev, sdev); busid_priv->sdev = sdev; - err = stub_add_files(&interface->dev); + err = stub_add_files(&udev->dev); if (err) { - dev_err(&interface->dev, "stub_add_files for %s\n", udev_busid); - usb_set_intfdata(interface, NULL); - usb_put_intf(interface); + dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); + dev_set_drvdata(&udev->dev, NULL); usb_put_dev(udev); kthread_stop_put(sdev->ud.eh); - busid_priv->interf_count = 0; busid_priv->sdev = NULL; stub_device_free(sdev); return err; @@ -461,13 +423,13 @@ static void shutdown_busid(struct bus_id_priv *busid_priv) * called in usb_disconnect() or usb_deregister() * but only if actconfig(active configuration) exists */ -static void stub_disconnect(struct usb_interface *interface) +static void stub_disconnect(struct usb_device *udev) { struct stub_device *sdev; - const char *udev_busid = dev_name(interface->dev.parent); + const char *udev_busid = dev_name(&udev->dev); struct bus_id_priv *busid_priv; - dev_dbg(&interface->dev, "Enter\n"); + dev_dbg(&udev->dev, "Enter\n"); busid_priv = get_busid_priv(udev_busid); if (!busid_priv) { @@ -475,41 +437,29 @@ static void stub_disconnect(struct usb_interface *interface) return; } - sdev = usb_get_intfdata(interface); + sdev = dev_get_drvdata(&udev->dev); /* get stub_device */ if (!sdev) { - dev_err(&interface->dev, "could not get device"); + dev_err(&udev->dev, "could not get device"); return; } - usb_set_intfdata(interface, NULL); + dev_set_drvdata(&udev->dev, NULL); /* * NOTE: rx/tx threads are invoked for each usb_device. */ - stub_remove_files(&interface->dev); + stub_remove_files(&udev->dev); /* If usb reset is called from event handler */ - if (busid_priv->sdev->ud.eh == current) { - busid_priv->interf_count--; + if (busid_priv->sdev->ud.eh == current) return; - } - - if (busid_priv->interf_count > 1) { - busid_priv->interf_count--; - shutdown_busid(busid_priv); - usb_put_intf(interface); - return; - } - - busid_priv->interf_count = 0; /* shutdown the current connection */ shutdown_busid(busid_priv); usb_put_dev(sdev->udev); - usb_put_intf(interface); /* free sdev */ busid_priv->sdev = NULL; @@ -523,28 +473,34 @@ static void stub_disconnect(struct usb_interface *interface) } } -/* - * Presence of pre_reset and post_reset prevents the driver from being unbound - * when the device is being reset - */ +#ifdef CONFIG_PM -static int stub_pre_reset(struct usb_interface *interface) +/* These functions need usb_port_suspend and usb_port_resume, + * which reside in drivers/usb/core/usb.h. Skip for now. */ + +static int stub_suspend(struct usb_device *udev, pm_message_t message) { - dev_dbg(&interface->dev, "pre_reset\n"); + dev_dbg(&udev->dev, "stub_suspend\n"); + return 0; } -static int stub_post_reset(struct usb_interface *interface) +static int stub_resume(struct usb_device *udev, pm_message_t message) { - dev_dbg(&interface->dev, "post_reset\n"); + dev_dbg(&udev->dev, "stub_resume\n"); + return 0; } -struct usb_driver stub_driver = { +#endif /* CONFIG_PM */ + +struct usb_device_driver stub_driver = { .name = "usbip-host", .probe = stub_probe, .disconnect = stub_disconnect, - .id_table = stub_table, - .pre_reset = stub_pre_reset, - .post_reset = stub_post_reset, +#ifdef CONFIG_PM + .suspend = stub_suspend, + .resume = stub_resume, +#endif + .supports_autosuspend = 0, }; diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c index baf857f7cc88..bd7b83a9d758 100644 --- a/drivers/staging/usbip/stub_main.c +++ b/drivers/staging/usbip/stub_main.c @@ -254,7 +254,7 @@ static int __init usbip_host_init(void) return -ENOMEM; } - ret = usb_register(&stub_driver); + ret = usb_register_device_driver(&stub_driver, THIS_MODULE); if (ret) { pr_err("usb_register failed %d\n", ret); goto err_usb_register; @@ -271,7 +271,7 @@ static int __init usbip_host_init(void) return ret; err_create_file: - usb_deregister(&stub_driver); + usb_deregister_device_driver(&stub_driver); err_usb_register: kmem_cache_destroy(stub_priv_cache); return ret; @@ -286,7 +286,7 @@ static void __exit usbip_host_exit(void) * deregister() calls stub_disconnect() for all devices. Device * specific data is cleared in stub_disconnect(). */ - usb_deregister(&stub_driver); + usb_deregister_device_driver(&stub_driver); kmem_cache_destroy(stub_priv_cache); } diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 5d1d4a183300..76e44d949232 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -550,7 +550,7 @@ static void stub_rx_pdu(struct usbip_device *ud) int ret; struct usbip_header pdu; struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct device *dev = &sdev->interface->dev; + struct device *dev = &sdev->udev->dev; usbip_dbg_stub_rx("Enter\n"); diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c index 71a449cf50db..86a867582de6 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c @@ -32,7 +32,6 @@ struct usbip_host_driver *host_driver; #define SYSFS_OPEN_RETRIES 100 -/* only the first interface value is true! */ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { char attrpath[SYSFS_PATH_MAX]; @@ -56,8 +55,8 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) * usbip_status to reappear. */ - snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", - udev->path, udev->busid, udev->bConfigurationValue, 0); + snprintf(attrpath, SYSFS_PATH_MAX, "%s/usbip_status", + udev->path); while (retries > 0) { if (stat(attrpath, &s) == 0) @@ -168,19 +167,18 @@ static void delete_nothing(void *unused_data) static int refresh_exported_devices(void) { - /* sysfs_device of usb_interface */ - struct sysfs_device *suintf; - struct dlist *suintf_list; /* sysfs_device of usb_device */ struct sysfs_device *sudev; struct dlist *sudev_list; + struct dlist *sudev_unique_list; struct usbip_exported_device *edev; - sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), - delete_nothing); + sudev_unique_list = dlist_new_with_delete(sizeof(struct sysfs_device), + delete_nothing); - suintf_list = sysfs_get_driver_devices(host_driver->sysfs_driver); - if (!suintf_list) { + sudev_list = sysfs_get_driver_devices(host_driver->sysfs_driver); + + if (!sudev_list) { /* * Not an error condition. There are simply no devices bound to * the driver yet. @@ -190,23 +188,13 @@ static int refresh_exported_devices(void) return 0; } - /* collect unique USB devices (not interfaces) */ - dlist_for_each_data(suintf_list, suintf, struct sysfs_device) { - /* get usb device of this usb interface */ - sudev = sysfs_get_device_parent(suintf); - if (!sudev) { - dbg("sysfs_get_device_parent failed: %s", suintf->name); - continue; - } + dlist_for_each_data(sudev_list, sudev, struct sysfs_device) + if (check_new(sudev_unique_list, sudev)) + dlist_unshift(sudev_unique_list, sudev); - if (check_new(sudev_list, sudev)) { - /* insert item at head of list */ - dlist_unshift(sudev_list, sudev); - } - } - - dlist_for_each_data(sudev_list, sudev, struct sysfs_device) { + dlist_for_each_data(sudev_unique_list, sudev, struct sysfs_device) { edev = usbip_exported_device_new(sudev->path); + if (!edev) { dbg("usbip_exported_device_new failed"); continue; @@ -216,7 +204,7 @@ static int refresh_exported_devices(void) host_driver->ndevs++; } - dlist_destroy(sudev_list); + dlist_destroy(sudev_unique_list); return 0; } @@ -356,9 +344,8 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) } /* only the first interface is true */ - snprintf(attr_path, sizeof(attr_path), "%s/%s:%d.%d/%s", - edev->udev.path, edev->udev.busid, - edev->udev.bConfigurationValue, 0, attr_name); + snprintf(attr_path, sizeof(attr_path), "%s/%s", + edev->udev.path, attr_name); attr = sysfs_open_attribute(attr_path); if (!attr) { diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c index 9ecaf6e574df..8cfd2dbd9510 100644 --- a/drivers/staging/usbip/userspace/src/usbip_bind.c +++ b/drivers/staging/usbip/userspace/src/usbip_bind.c @@ -52,12 +52,8 @@ static int bind_usbip(char *busid) char attr_name[] = "bind"; char sysfs_mntpath[SYSFS_PATH_MAX]; char bind_attr_path[SYSFS_PATH_MAX]; - char intf_busid[SYSFS_BUS_ID_SIZE]; - struct sysfs_device *busid_dev; struct sysfs_attribute *bind_attr; - struct sysfs_attribute *bConfValue; - struct sysfs_attribute *bNumIntfs; - int i, failed = 0; + int failed = 0; int rc, ret = -1; rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); @@ -76,39 +72,15 @@ static int bind_usbip(char *busid) return -1; } - busid_dev = sysfs_open_device(bus_type, busid); - if (!busid_dev) { - dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); - goto err_close_bind_attr; - } - - bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); - bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); - - if (!bConfValue || !bNumIntfs) { - dbg("problem getting device attributes: %s", - strerror(errno)); - goto err_close_busid_dev; - } - - for (i = 0; i < atoi(bNumIntfs->value); i++) { - snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, - bConfValue->value, i); - - rc = sysfs_write_attribute(bind_attr, intf_busid, - SYSFS_BUS_ID_SIZE); - if (rc < 0) { - dbg("bind driver at %s failed", intf_busid); - failed = 1; - } + rc = sysfs_write_attribute(bind_attr, busid, SYSFS_BUS_ID_SIZE); + if (rc < 0) { + dbg("bind driver at %s failed", busid); + failed = 1; } if (!failed) ret = 0; -err_close_busid_dev: - sysfs_close_device(busid_dev); -err_close_bind_attr: sysfs_close_attribute(bind_attr); return ret; @@ -118,15 +90,12 @@ err_close_bind_attr: static int unbind_other(char *busid) { char bus_type[] = "usb"; - char intf_busid[SYSFS_BUS_ID_SIZE]; struct sysfs_device *busid_dev; - struct sysfs_device *intf_dev; - struct sysfs_driver *intf_drv; + struct sysfs_device *dev; + struct sysfs_driver *drv; struct sysfs_attribute *unbind_attr; - struct sysfs_attribute *bConfValue; struct sysfs_attribute *bDevClass; - struct sysfs_attribute *bNumIntfs; - int i, rc; + int rc; enum unbind_status status = UNBIND_ST_OK; busid_dev = sysfs_open_device(bus_type, busid); @@ -134,12 +103,11 @@ static int unbind_other(char *busid) dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); return -1; } + dbg("busid path: %s", busid_dev->path); - bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); bDevClass = sysfs_get_device_attr(busid_dev, "bDeviceClass"); - bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); - if (!bConfValue || !bDevClass || !bNumIntfs) { - dbg("problem getting device attributes: %s", + if (!bDevClass) { + dbg("problem getting device attribute: %s", strerror(errno)); goto err_close_busid_dev; } @@ -149,62 +117,62 @@ static int unbind_other(char *busid) goto err_close_busid_dev; } - for (i = 0; i < atoi(bNumIntfs->value); i++) { - snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, - bConfValue->value, i); - intf_dev = sysfs_open_device(bus_type, intf_busid); - if (!intf_dev) { - dbg("could not open interface device: %s", - strerror(errno)); - goto err_close_busid_dev; - } - - dbg("%s -> %s", intf_dev->name, intf_dev->driver_name); + dev = sysfs_open_device(bus_type, busid); + if (!dev) { + dbg("could not open device: %s", + strerror(errno)); + goto err_close_busid_dev; + } - if (!strncmp("unknown", intf_dev->driver_name, SYSFS_NAME_LEN)) - /* unbound interface */ - continue; + dbg("%s -> %s", dev->name, dev->driver_name); - if (!strncmp(USBIP_HOST_DRV_NAME, intf_dev->driver_name, - SYSFS_NAME_LEN)) { - /* already bound to usbip-host */ - status = UNBIND_ST_USBIP_HOST; - continue; - } + if (!strncmp("unknown", dev->driver_name, SYSFS_NAME_LEN)) { + /* unbound interface */ + sysfs_close_device(dev); + goto out; + } - /* unbinding */ - intf_drv = sysfs_open_driver(bus_type, intf_dev->driver_name); - if (!intf_drv) { - dbg("could not open interface driver on %s: %s", - intf_dev->name, strerror(errno)); - goto err_close_intf_dev; - } + if (!strncmp(USBIP_HOST_DRV_NAME, dev->driver_name, + SYSFS_NAME_LEN)) { + /* already bound to usbip-host */ + status = UNBIND_ST_USBIP_HOST; + sysfs_close_device(dev); + goto out; + } - unbind_attr = sysfs_get_driver_attr(intf_drv, "unbind"); - if (!unbind_attr) { - dbg("problem getting interface driver attribute: %s", - strerror(errno)); - goto err_close_intf_drv; - } + /* unbinding */ + drv = sysfs_open_driver(bus_type, dev->driver_name); + if (!drv) { + dbg("could not open device driver on %s: %s", + dev->name, strerror(errno)); + goto err_close_intf_dev; + } + dbg("device driver: %s", drv->path); - rc = sysfs_write_attribute(unbind_attr, intf_dev->bus_id, - SYSFS_BUS_ID_SIZE); - if (rc < 0) { - /* NOTE: why keep unbinding other interfaces? */ - dbg("unbind driver at %s failed", intf_dev->bus_id); - status = UNBIND_ST_FAILED; - } + unbind_attr = sysfs_get_driver_attr(drv, "unbind"); + if (!unbind_attr) { + dbg("problem getting device driver attribute: %s", + strerror(errno)); + goto err_close_intf_drv; + } - sysfs_close_driver(intf_drv); - sysfs_close_device(intf_dev); + rc = sysfs_write_attribute(unbind_attr, dev->bus_id, + SYSFS_BUS_ID_SIZE); + if (rc < 0) { + /* NOTE: why keep unbinding other interfaces? */ + dbg("unbind driver at %s failed", dev->bus_id); + status = UNBIND_ST_FAILED; } + sysfs_close_driver(drv); + sysfs_close_device(dev); + goto out; err_close_intf_drv: - sysfs_close_driver(intf_drv); + sysfs_close_driver(drv); err_close_intf_dev: - sysfs_close_device(intf_dev); + sysfs_close_device(dev); err_close_busid_dev: status = UNBIND_ST_FAILED; out: diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c index 237e099337a1..8864fa2a7f0b 100644 --- a/drivers/staging/usbip/userspace/src/usbip_list.c +++ b/drivers/staging/usbip/userspace/src/usbip_list.c @@ -52,9 +52,8 @@ static int get_exported_devices(char *host, int sockfd) struct op_devlist_reply reply; uint16_t code = OP_REP_DEVLIST; struct usbip_usb_device udev; - struct usbip_usb_interface uintf; unsigned int i; - int j, rc; + int rc; rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); if (rc < 0) { @@ -104,22 +103,6 @@ static int get_exported_devices(char *host, int sockfd) printf("%11s: %s\n", "", udev.path); printf("%11s: %s\n", "", class_name); - for (j = 0; j < udev.bNumInterfaces; j++) { - rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); - if (rc < 0) { - dbg("usbip_net_recv failed: usbip_usb_intf[%d]", - j); - - return -1; - } - usbip_net_pack_usb_interface(0, &uintf); - - usbip_names_get_class(class_name, sizeof(class_name), - uintf.bInterfaceClass, - uintf.bInterfaceSubClass, - uintf.bInterfaceProtocol); - printf("%11s: %2d - %s\n", "", j, class_name); - } printf("\n"); } diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c index d5a9ab6af2a6..cace87838c24 100644 --- a/drivers/staging/usbip/userspace/src/usbip_unbind.c +++ b/drivers/staging/usbip/userspace/src/usbip_unbind.c @@ -47,12 +47,10 @@ static int unbind_device(char *busid) int verified = 0; int rc, ret = -1; - char attr_name[] = "bConfigurationValue"; + char attr_name[] = "unbind"; char sysfs_mntpath[SYSFS_PATH_MAX]; - char busid_attr_path[SYSFS_PATH_MAX]; - struct sysfs_attribute *busid_attr; - char *val = NULL; - int len; + char unbind_attr_path[SYSFS_PATH_MAX]; + struct sysfs_attribute *unbind_attr; /* verify the busid device is using usbip-host */ usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME); @@ -99,55 +97,34 @@ static int unbind_device(char *busid) return -1; } - snprintf(busid_attr_path, sizeof(busid_attr_path), "%s/%s/%s/%s/%s/%s", - sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DEVICES_NAME, - busid, attr_name); + snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", + sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, + USBIP_HOST_DRV_NAME, attr_name); /* read a device attribute */ - busid_attr = sysfs_open_attribute(busid_attr_path); - if (!busid_attr) { + unbind_attr = sysfs_open_attribute(unbind_attr_path); + if (!unbind_attr) { err("could not open %s/%s: %s", busid, attr_name, strerror(errno)); return -1; } - if (sysfs_read_attribute(busid_attr) < 0) { - err("problem reading attribute: %s", strerror(errno)); - goto err_out; - } - - len = busid_attr->len; - val = malloc(len); - *val = *busid_attr->value; - sysfs_close_attribute(busid_attr); - /* notify driver of unbind */ rc = modify_match_busid(busid, 0); if (rc < 0) { err("unable to unbind device on %s", busid); - goto err_out; - } - - /* write the device attribute */ - busid_attr = sysfs_open_attribute(busid_attr_path); - if (!busid_attr) { - err("could not open %s/%s: %s", busid, attr_name, - strerror(errno)); - return -1; } - rc = sysfs_write_attribute(busid_attr, val, len); - if (rc < 0) { - err("problem writing attribute: %s", strerror(errno)); - goto err_out; - } - sysfs_close_attribute(busid_attr); + rc = sysfs_write_attribute(unbind_attr, busid, + SYSFS_BUS_ID_SIZE); + if (rc < 0) { + dbg("bind driver at %s failed", busid); + } + sysfs_close_attribute(unbind_attr); ret = 0; printf("unbind device on busid %s: complete\n", busid); -err_out: - free(val); err_close_usbip_host_drv: sysfs_close_driver(usbip_host_drv); diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 7980f8b5517b..c2b3ced9ca6e 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -159,9 +159,7 @@ static int send_reply_devlist(int connfd) { struct usbip_exported_device *edev; struct usbip_usb_device pdu_udev; - struct usbip_usb_interface pdu_uinf; struct op_devlist_reply reply; - int i; int rc; reply.ndev = 0; @@ -196,19 +194,6 @@ static int send_reply_devlist(int connfd) dbg("usbip_net_send failed: pdu_udev"); return -1; } - - for (i = 0; i < edev->udev.bNumInterfaces; i++) { - dump_usb_interface(&edev->uinf[i]); - memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); - usbip_net_pack_usb_interface(1, &pdu_uinf); - - rc = usbip_net_send(connfd, &pdu_uinf, - sizeof(pdu_uinf)); - if (rc < 0) { - dbg("usbip_net_send failed: pdu_uinf"); - return -1; - } - } } return 0; diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index acbfeb0a0119..358ca8dd784f 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -155,6 +155,7 @@ int usb_choose_configuration(struct usb_device *udev) } return i; } +EXPORT_SYMBOL_GPL(usb_choose_configuration); static int generic_probe(struct usb_device *udev) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f829a1aad1c3..08d95e9d56c2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1920,6 +1920,7 @@ free_interfaces: usb_autosuspend_device(dev); return 0; } +EXPORT_SYMBOL_GPL(usb_set_configuration); static LIST_HEAD(set_config_list); static DEFINE_SPINLOCK(set_config_lock); diff --git a/include/linux/usb.h b/include/linux/usb.h index c716da18c668..f434619f3975 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1668,6 +1668,10 @@ extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr); /* this request isn't really synchronous, but it belongs with the others */ extern int usb_driver_set_configuration(struct usb_device *udev, int config); +/* choose and set configuration for device */ +extern int usb_choose_configuration(struct usb_device *udev); +extern int usb_set_configuration(struct usb_device *dev, int configuration); + /* * timeouts, in milliseconds, used for sending/receiving control messages * they typically complete within a few frames (msec) after they're issued -- cgit v1.2.3 From 07d4655b410a4da3bdffbc9ed01d9fef67f682a6 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 12 Nov 2013 18:45:00 +0000 Subject: iio:drop IIO_ST macro This macro no longer allows all the elements of the scan_type structure to be set. Missinterpretation of the parameters also caused a couple of recent bugs. No mainline drivers now use this macro so drop it. Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 75a8a20c8179..5f2d00e7e488 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -254,12 +254,16 @@ static inline bool iio_channel_has_info(const struct iio_chan_spec *chan, (chan->info_mask_shared_by_all & BIT(type)); } -#define IIO_ST(si, rb, sb, sh) \ - { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } - -#define IIO_CHAN_SOFT_TIMESTAMP(_si) \ - { .type = IIO_TIMESTAMP, .channel = -1, \ - .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } +#define IIO_CHAN_SOFT_TIMESTAMP(_si) { \ + .type = IIO_TIMESTAMP, \ + .channel = -1, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 64, \ + .storagebits = 64, \ + }, \ +} /** * iio_get_time_ns() - utility function to get a time stamp for events etc -- cgit v1.2.3 From 39a3a0138f6113805dc9e0813214cd4b03bd8ac0 Mon Sep 17 00:00:00 2001 From: Archana Patni Date: Thu, 20 Feb 2014 06:29:00 +0000 Subject: iio: hid-sensors: Added Proximity Sensor Driver Added usage id processing for Proximity (Human Presence). This uses IIO interfaces for triggered buffer to present data to user mode. This uses HID sensor framework for registering callback events from the sensor hub. Signed-off-by: Archana Patni Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/light/Kconfig | 14 ++ drivers/iio/light/Makefile | 1 + drivers/iio/light/hid-sensor-prox.c | 375 ++++++++++++++++++++++++++++++++++++ include/linux/hid-sensor-ids.h | 5 + 4 files changed, 395 insertions(+) create mode 100644 drivers/iio/light/hid-sensor-prox.c (limited to 'include') diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 3a7a5d9f03a3..c89740d4748f 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -73,6 +73,20 @@ config HID_SENSOR_ALS Say yes here to build support for the HID SENSOR Ambient light sensor. +config HID_SENSOR_PROX + depends on HID_SENSOR_HUB + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER + tristate "HID PROX" + help + Say yes here to build support for the HID SENSOR + Proximity sensor. + + To compile this driver as a module, choose M here: the + module will be called hid-sensor-prox. + config SENSORS_LM3533 tristate "LM3533 ambient light sensor" depends on MFD_LM3533 diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 924530597f83..3eb36e5151fa 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CM32181) += cm32181.o obj-$(CONFIG_CM36651) += cm36651.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o +obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c new file mode 100644 index 000000000000..1894ab196f97 --- /dev/null +++ b/drivers/iio/light/hid-sensor-prox.c @@ -0,0 +1,375 @@ +/* + * HID Sensors Driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/hid-sensors/hid-sensor-trigger.h" + +#define CHANNEL_SCAN_INDEX_PRESENCE 0 + +struct prox_state { + struct hid_sensor_hub_callbacks callbacks; + struct hid_sensor_common common_attributes; + struct hid_sensor_hub_attribute_info prox_attr; + u32 human_presence; +}; + +/* Channel definitions */ +static const struct iio_chan_spec prox_channels[] = { + { + .type = IIO_PROXIMITY, + .modified = 1, + .channel2 = IIO_NO_MOD, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_PRESENCE, + } +}; + +/* Adjust channel real bits based on report descriptor */ +static void prox_adjust_channel_bit_mask(struct iio_chan_spec *channels, + int channel, int size) +{ + channels[channel].scan_type.sign = 's'; + /* Real storage bits will change based on the report desc. */ + channels[channel].scan_type.realbits = size * 8; + /* Maximum size of a sample to capture is u32 */ + channels[channel].scan_type.storagebits = sizeof(u32) * 8; +} + +/* Channel read_raw handler */ +static int prox_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct prox_state *prox_state = iio_priv(indio_dev); + int report_id = -1; + u32 address; + int ret; + int ret_type; + + *val = 0; + *val2 = 0; + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->scan_index) { + case CHANNEL_SCAN_INDEX_PRESENCE: + report_id = prox_state->prox_attr.report_id; + address = + HID_USAGE_SENSOR_HUMAN_PRESENCE; + break; + default: + report_id = -1; + break; + } + if (report_id >= 0) + *val = sensor_hub_input_attr_get_raw_value( + prox_state->common_attributes.hsdev, + HID_USAGE_SENSOR_PROX, address, + report_id); + else { + *val = 0; + return -EINVAL; + } + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = prox_state->prox_attr.units; + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OFFSET: + *val = hid_sensor_convert_exponent( + prox_state->prox_attr.unit_expo); + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hid_sensor_read_samp_freq_value( + &prox_state->common_attributes, val, val2); + ret_type = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret = hid_sensor_read_raw_hyst_value( + &prox_state->common_attributes, val, val2); + ret_type = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret_type = -EINVAL; + break; + } + + return ret_type; +} + +/* Channel write_raw handler */ +static int prox_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct prox_state *prox_state = iio_priv(indio_dev); + int ret = 0; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hid_sensor_write_samp_freq_value( + &prox_state->common_attributes, val, val2); + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret = hid_sensor_write_raw_hyst_value( + &prox_state->common_attributes, val, val2); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info prox_info = { + .driver_module = THIS_MODULE, + .read_raw = &prox_read_raw, + .write_raw = &prox_write_raw, +}; + +/* Function to push data to buffer */ +static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, + int len) +{ + dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); + iio_push_to_buffers(indio_dev, data); +} + +/* Callback handler to send event after all samples are received and captured */ +static int prox_proc_event(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct prox_state *prox_state = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "prox_proc_event [%d]\n", + prox_state->common_attributes.data_ready); + if (prox_state->common_attributes.data_ready) + hid_sensor_push_data(indio_dev, + &prox_state->human_presence, + sizeof(prox_state->human_presence)); + + return 0; +} + +/* Capture samples in local storage */ +static int prox_capture_sample(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + size_t raw_len, char *raw_data, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct prox_state *prox_state = iio_priv(indio_dev); + int ret = -EINVAL; + + switch (usage_id) { + case HID_USAGE_SENSOR_HUMAN_PRESENCE: + prox_state->human_presence = *(u32 *)raw_data; + ret = 0; + break; + default: + break; + } + + return ret; +} + +/* Parse report which is specific to an usage id*/ +static int prox_parse_report(struct platform_device *pdev, + struct hid_sensor_hub_device *hsdev, + struct iio_chan_spec *channels, + unsigned usage_id, + struct prox_state *st) +{ + int ret; + + ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, + usage_id, + HID_USAGE_SENSOR_HUMAN_PRESENCE, + &st->prox_attr); + if (ret < 0) + return ret; + prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE, + st->prox_attr.size); + + dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index, + st->prox_attr.report_id); + + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_PRESENCE, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } + return ret; +} + +/* Function to initialize the processing for usage id */ +static int hid_prox_probe(struct platform_device *pdev) +{ + int ret = 0; + static const char *name = "prox"; + struct iio_dev *indio_dev; + struct prox_state *prox_state; + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_chan_spec *channels; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct prox_state)); + if (!indio_dev) + return -ENOMEM; + platform_set_drvdata(pdev, indio_dev); + + prox_state = iio_priv(indio_dev); + prox_state->common_attributes.hsdev = hsdev; + prox_state->common_attributes.pdev = pdev; + + ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_PROX, + &prox_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "failed to setup common attributes\n"); + return ret; + } + + channels = kmemdup(prox_channels, sizeof(prox_channels), GFP_KERNEL); + if (!channels) { + dev_err(&pdev->dev, "failed to duplicate channels\n"); + return -ENOMEM; + } + + ret = prox_parse_report(pdev, hsdev, channels, + HID_USAGE_SENSOR_PROX, prox_state); + if (ret) { + dev_err(&pdev->dev, "failed to setup attributes\n"); + goto error_free_dev_mem; + } + + indio_dev->channels = channels; + indio_dev->num_channels = + ARRAY_SIZE(prox_channels); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &prox_info; + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + NULL, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); + goto error_free_dev_mem; + } + prox_state->common_attributes.data_ready = false; + ret = hid_sensor_setup_trigger(indio_dev, name, + &prox_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "trigger setup failed\n"); + goto error_unreg_buffer_funcs; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "device register failed\n"); + goto error_remove_trigger; + } + + prox_state->callbacks.send_event = prox_proc_event; + prox_state->callbacks.capture_sample = prox_capture_sample; + prox_state->callbacks.pdev = pdev; + ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_PROX, + &prox_state->callbacks); + if (ret < 0) { + dev_err(&pdev->dev, "callback reg failed\n"); + goto error_iio_unreg; + } + + return ret; + +error_iio_unreg: + iio_device_unregister(indio_dev); +error_remove_trigger: + hid_sensor_remove_trigger(&prox_state->common_attributes); +error_unreg_buffer_funcs: + iio_triggered_buffer_cleanup(indio_dev); +error_free_dev_mem: + kfree(indio_dev->channels); + return ret; +} + +/* Function to deinitialize the processing for usage id */ +static int hid_prox_remove(struct platform_device *pdev) +{ + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct prox_state *prox_state = iio_priv(indio_dev); + + sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PROX); + iio_device_unregister(indio_dev); + hid_sensor_remove_trigger(&prox_state->common_attributes); + iio_triggered_buffer_cleanup(indio_dev); + kfree(indio_dev->channels); + + return 0; +} + +static struct platform_device_id hid_prox_ids[] = { + { + /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ + .name = "HID-SENSOR-200011", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, hid_prox_ids); + +static struct platform_driver hid_prox_platform_driver = { + .id_table = hid_prox_ids, + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .probe = hid_prox_probe, + .remove = hid_prox_remove, +}; +module_platform_driver(hid_prox_platform_driver); + +MODULE_DESCRIPTION("HID Sensor Proximity"); +MODULE_AUTHOR("Archana Patni "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index beaf965621c1..9bc9e35f1b3f 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -33,6 +33,11 @@ #define HID_USAGE_SENSOR_DATA_LIGHT 0x2004d0 #define HID_USAGE_SENSOR_LIGHT_ILLUM 0x2004d1 +/* PROX (200011) */ +#define HID_USAGE_SENSOR_PROX 0x200011 +#define HID_USAGE_SENSOR_DATA_PRESENCE 0x2004b0 +#define HID_USAGE_SENSOR_HUMAN_PRESENCE 0x2004b1 + /* Gyro 3D: (200076) */ #define HID_USAGE_SENSOR_GYRO_3D 0x200076 #define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456 -- cgit v1.2.3 From f64a799b8a49e3e26497b26ea78af01fc6302874 Mon Sep 17 00:00:00 2001 From: Archana Patni Date: Thu, 20 Feb 2014 06:30:00 +0000 Subject: iio: hid-sensors: Added Pressure Sensor driver Added usage id processing for Pressure Sensor. This uses IIO interfaces for triggered buffer to present data to user mode. This uses HID sensor framework for registering callback events from the sensor hub. Signed-off-by: Archana Patni Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 14 ++ drivers/iio/pressure/Makefile | 1 + drivers/iio/pressure/hid-sensor-press.c | 376 ++++++++++++++++++++++++++++++++ include/linux/hid-sensor-ids.h | 5 + 4 files changed, 396 insertions(+) create mode 100644 drivers/iio/pressure/hid-sensor-press.c (limited to 'include') diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index a8b9cae5c173..6215761b3c53 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -5,6 +5,20 @@ menu "Pressure sensors" +config HID_SENSOR_PRESS + depends on HID_SENSOR_HUB + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select HID_SENSOR_IIO_COMMON + select HID_SENSOR_IIO_TRIGGER + tristate "HID PRESS" + help + Say yes here to build support for the HID SENSOR + Pressure driver + + To compile this driver as a module, choose M here: the module + will be called hid-sensor-press. + config MPL3115 tristate "Freescale MPL3115A2 pressure sensor driver" depends on I2C diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 42bb9fcf5436..4a57bf65b04b 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -3,6 +3,7 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o obj-$(CONFIG_MPL3115) += mpl3115.o obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o st_pressure-y := st_pressure_core.o diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c new file mode 100644 index 000000000000..e0e6409aa94e --- /dev/null +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -0,0 +1,376 @@ +/* + * HID Sensors Driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/hid-sensors/hid-sensor-trigger.h" + +#define CHANNEL_SCAN_INDEX_PRESSURE 0 + +struct press_state { + struct hid_sensor_hub_callbacks callbacks; + struct hid_sensor_common common_attributes; + struct hid_sensor_hub_attribute_info press_attr; + u32 press_data; +}; + +/* Channel definitions */ +static const struct iio_chan_spec press_channels[] = { + { + .type = IIO_PRESSURE, + .modified = 1, + .channel2 = IIO_NO_MOD, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_HYSTERESIS), + .scan_index = CHANNEL_SCAN_INDEX_PRESSURE, + } +}; + +/* Adjust channel real bits based on report descriptor */ +static void press_adjust_channel_bit_mask(struct iio_chan_spec *channels, + int channel, int size) +{ + channels[channel].scan_type.sign = 's'; + /* Real storage bits will change based on the report desc. */ + channels[channel].scan_type.realbits = size * 8; + /* Maximum size of a sample to capture is u32 */ + channels[channel].scan_type.storagebits = sizeof(u32) * 8; +} + +/* Channel read_raw handler */ +static int press_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct press_state *press_state = iio_priv(indio_dev); + int report_id = -1; + u32 address; + int ret; + int ret_type; + + *val = 0; + *val2 = 0; + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->scan_index) { + case CHANNEL_SCAN_INDEX_PRESSURE: + report_id = press_state->press_attr.report_id; + address = + HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE; + break; + default: + report_id = -1; + break; + } + if (report_id >= 0) + *val = sensor_hub_input_attr_get_raw_value( + press_state->common_attributes.hsdev, + HID_USAGE_SENSOR_PRESSURE, address, + report_id); + else { + *val = 0; + return -EINVAL; + } + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + *val = press_state->press_attr.units; + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OFFSET: + *val = hid_sensor_convert_exponent( + press_state->press_attr.unit_expo); + ret_type = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hid_sensor_read_samp_freq_value( + &press_state->common_attributes, val, val2); + ret_type = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret = hid_sensor_read_raw_hyst_value( + &press_state->common_attributes, val, val2); + ret_type = IIO_VAL_INT_PLUS_MICRO; + break; + default: + ret_type = -EINVAL; + break; + } + + return ret_type; +} + +/* Channel write_raw handler */ +static int press_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct press_state *press_state = iio_priv(indio_dev); + int ret = 0; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = hid_sensor_write_samp_freq_value( + &press_state->common_attributes, val, val2); + break; + case IIO_CHAN_INFO_HYSTERESIS: + ret = hid_sensor_write_raw_hyst_value( + &press_state->common_attributes, val, val2); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static const struct iio_info press_info = { + .driver_module = THIS_MODULE, + .read_raw = &press_read_raw, + .write_raw = &press_write_raw, +}; + +/* Function to push data to buffer */ +static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data, + int len) +{ + dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); + iio_push_to_buffers(indio_dev, data); +} + +/* Callback handler to send event after all samples are received and captured */ +static int press_proc_event(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct press_state *press_state = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "press_proc_event [%d]\n", + press_state->common_attributes.data_ready); + if (press_state->common_attributes.data_ready) + hid_sensor_push_data(indio_dev, + &press_state->press_data, + sizeof(press_state->press_data)); + + return 0; +} + +/* Capture samples in local storage */ +static int press_capture_sample(struct hid_sensor_hub_device *hsdev, + unsigned usage_id, + size_t raw_len, char *raw_data, + void *priv) +{ + struct iio_dev *indio_dev = platform_get_drvdata(priv); + struct press_state *press_state = iio_priv(indio_dev); + int ret = -EINVAL; + + switch (usage_id) { + case HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE: + press_state->press_data = *(u32 *)raw_data; + ret = 0; + break; + default: + break; + } + + return ret; +} + +/* Parse report which is specific to an usage id*/ +static int press_parse_report(struct platform_device *pdev, + struct hid_sensor_hub_device *hsdev, + struct iio_chan_spec *channels, + unsigned usage_id, + struct press_state *st) +{ + int ret; + + ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT, + usage_id, + HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE, + &st->press_attr); + if (ret < 0) + return ret; + press_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESSURE, + st->press_attr.size); + + dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index, + st->press_attr.report_id); + + /* Set Sensitivity field ids, when there is no individual modifier */ + if (st->common_attributes.sensitivity.index < 0) { + sensor_hub_input_get_attribute_info(hsdev, + HID_FEATURE_REPORT, usage_id, + HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS | + HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE, + &st->common_attributes.sensitivity); + dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n", + st->common_attributes.sensitivity.index, + st->common_attributes.sensitivity.report_id); + } + return ret; +} + +/* Function to initialize the processing for usage id */ +static int hid_press_probe(struct platform_device *pdev) +{ + int ret = 0; + static const char *name = "press"; + struct iio_dev *indio_dev; + struct press_state *press_state; + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_chan_spec *channels; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct press_state)); + if (!indio_dev) + return -ENOMEM; + platform_set_drvdata(pdev, indio_dev); + + press_state = iio_priv(indio_dev); + press_state->common_attributes.hsdev = hsdev; + press_state->common_attributes.pdev = pdev; + + ret = hid_sensor_parse_common_attributes(hsdev, + HID_USAGE_SENSOR_PRESSURE, + &press_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "failed to setup common attributes\n"); + return ret; + } + + channels = kmemdup(press_channels, sizeof(press_channels), GFP_KERNEL); + if (!channels) { + dev_err(&pdev->dev, "failed to duplicate channels\n"); + return -ENOMEM; + } + + ret = press_parse_report(pdev, hsdev, channels, + HID_USAGE_SENSOR_PRESSURE, press_state); + if (ret) { + dev_err(&pdev->dev, "failed to setup attributes\n"); + goto error_free_dev_mem; + } + + indio_dev->channels = channels; + indio_dev->num_channels = + ARRAY_SIZE(press_channels); + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &press_info; + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + NULL, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to initialize trigger buffer\n"); + goto error_free_dev_mem; + } + press_state->common_attributes.data_ready = false; + ret = hid_sensor_setup_trigger(indio_dev, name, + &press_state->common_attributes); + if (ret) { + dev_err(&pdev->dev, "trigger setup failed\n"); + goto error_unreg_buffer_funcs; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&pdev->dev, "device register failed\n"); + goto error_remove_trigger; + } + + press_state->callbacks.send_event = press_proc_event; + press_state->callbacks.capture_sample = press_capture_sample; + press_state->callbacks.pdev = pdev; + ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_PRESSURE, + &press_state->callbacks); + if (ret < 0) { + dev_err(&pdev->dev, "callback reg failed\n"); + goto error_iio_unreg; + } + + return ret; + +error_iio_unreg: + iio_device_unregister(indio_dev); +error_remove_trigger: + hid_sensor_remove_trigger(&press_state->common_attributes); +error_unreg_buffer_funcs: + iio_triggered_buffer_cleanup(indio_dev); +error_free_dev_mem: + kfree(indio_dev->channels); + return ret; +} + +/* Function to deinitialize the processing for usage id */ +static int hid_press_remove(struct platform_device *pdev) +{ + struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct press_state *press_state = iio_priv(indio_dev); + + sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE); + iio_device_unregister(indio_dev); + hid_sensor_remove_trigger(&press_state->common_attributes); + iio_triggered_buffer_cleanup(indio_dev); + kfree(indio_dev->channels); + + return 0; +} + +static struct platform_device_id hid_press_ids[] = { + { + /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ + .name = "HID-SENSOR-200031", + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, hid_press_ids); + +static struct platform_driver hid_press_platform_driver = { + .id_table = hid_press_ids, + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .probe = hid_press_probe, + .remove = hid_press_remove, +}; +module_platform_driver(hid_press_platform_driver); + +MODULE_DESCRIPTION("HID Sensor Pressure"); +MODULE_AUTHOR("Archana Patni "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index 9bc9e35f1b3f..537161a997ab 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -38,6 +38,11 @@ #define HID_USAGE_SENSOR_DATA_PRESENCE 0x2004b0 #define HID_USAGE_SENSOR_HUMAN_PRESENCE 0x2004b1 +/* Pressure (200031) */ +#define HID_USAGE_SENSOR_PRESSURE 0x200031 +#define HID_USAGE_SENSOR_DATA_ATMOSPHERIC_PRESSURE 0x200430 +#define HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE 0x200431 + /* Gyro 3D: (200076) */ #define HID_USAGE_SENSOR_GYRO_3D 0x200076 #define HID_USAGE_SENSOR_DATA_ANGL_VELOCITY 0x200456 -- cgit v1.2.3 From fd9fdb78a9bf85b94fb2190c82ff280c8f8375cc Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 10 Feb 2014 22:01:48 +0100 Subject: [media] of: move graph helpers from drivers/media/v4l2-core to drivers/of This patch moves the parsing helpers used to parse connected graphs in the device tree, like the video interface bindings documented in Documentation/devicetree/bindings/media/video-interfaces.txt, from drivers/media/v4l2-core/v4l2-of.c into drivers/of/base.c. This allows to reuse the same parser code from outside the V4L2 framework, most importantly from display drivers. The functions v4l2_of_get_next_endpoint, v4l2_of_get_remote_port, and v4l2_of_get_remote_port_parent are moved. They are renamed to of_graph_get_next_endpoint, of_graph_get_remote_port, and of_graph_get_remote_port_parent, respectively. Since there are not that many current users yet, switch all of them to the new functions right away. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/media/i2c/adv7343.c | 4 +- drivers/media/i2c/mt9p031.c | 4 +- drivers/media/i2c/s5k5baf.c | 3 +- drivers/media/i2c/tvp514x.c | 3 +- drivers/media/i2c/tvp7002.c | 3 +- drivers/media/platform/exynos4-is/fimc-is.c | 6 +- drivers/media/platform/exynos4-is/media-dev.c | 3 +- drivers/media/platform/exynos4-is/mipi-csis.c | 3 +- drivers/media/v4l2-core/v4l2-of.c | 117 ------------------------- drivers/of/base.c | 118 ++++++++++++++++++++++++++ include/linux/of_graph.h | 46 ++++++++++ include/media/v4l2-of.h | 25 +----- 12 files changed, 182 insertions(+), 153 deletions(-) create mode 100644 include/linux/of_graph.h (limited to 'include') diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index d4e15a617c3b..9d38f7b36cd1 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -26,12 +26,12 @@ #include #include #include +#include #include #include #include #include -#include #include "adv7343_regs.h" @@ -410,7 +410,7 @@ adv7343_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_next_endpoint(client->dev.of_node, NULL); if (!np) return NULL; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index e5ddf47030fd..192c4aad05d6 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include #include "aptina-pll.h" @@ -943,7 +943,7 @@ mt9p031_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_next_endpoint(client->dev.of_node, NULL); if (!np) return NULL; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 77e10e0fd8d6..2d768ef67cc5 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -1855,7 +1856,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) if (ret < 0) return ret; - node_ep = v4l2_of_get_next_endpoint(node, NULL); + node_ep = of_graph_get_next_endpoint(node, NULL); if (!node_ep) { dev_err(dev, "no endpoint defined at node %s\n", node->full_name); diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 83d85df4853a..ca001178c5bf 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -1068,7 +1069,7 @@ tvp514x_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); if (!endpoint) return NULL; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 912e1cccdd1c..c4e1e2cb3094 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -957,7 +958,7 @@ tvp7002_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); if (!endpoint) return NULL; diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 13a4228952e3..9bdfa4599bc3 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -24,13 +24,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include "media-dev.h" @@ -167,10 +167,10 @@ static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor, u32 tmp = 0; int ret; - np = v4l2_of_get_next_endpoint(np, NULL); + np = of_graph_get_next_endpoint(np, NULL); if (!np) return -ENXIO; - np = v4l2_of_get_remote_port(np); + np = of_graph_get_remote_port(np); if (!np) return -ENXIO; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index c1bce170df6f..d0f82da59ac5 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -473,7 +474,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, pd->mux_id = (endpoint.port - 1) & 0x1; - rem = v4l2_of_get_remote_port_parent(ep); + rem = of_graph_get_remote_port_parent(ep); of_node_put(ep); if (rem == NULL) { v4l2_info(&fmd->v4l2_dev, "Remote device at %s not found\n", diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index f3c3591fdc5d..fd1ae6549607 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -762,7 +763,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, &state->max_num_lanes)) return -EINVAL; - node = v4l2_of_get_next_endpoint(node, NULL); + node = of_graph_get_next_endpoint(node, NULL); if (!node) { dev_err(&pdev->dev, "No port node at %s\n", pdev->dev.of_node->full_name); diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index 42e3e8a5e361..f919db358bbe 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -152,120 +152,3 @@ int v4l2_of_parse_endpoint(const struct device_node *node, return 0; } EXPORT_SYMBOL(v4l2_of_parse_endpoint); - -/** - * v4l2_of_get_next_endpoint() - get next endpoint node - * @parent: pointer to the parent device node - * @prev: previous endpoint node, or NULL to get first - * - * Return: An 'endpoint' node pointer with refcount incremented. Refcount - * of the passed @prev node is not decremented, the caller have to use - * of_node_put() on it when done. - */ -struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, - struct device_node *prev) -{ - struct device_node *endpoint; - struct device_node *port = NULL; - - if (!parent) - return NULL; - - if (!prev) { - struct device_node *node; - /* - * It's the first call, we have to find a port subnode - * within this node or within an optional 'ports' node. - */ - node = of_get_child_by_name(parent, "ports"); - if (node) - parent = node; - - port = of_get_child_by_name(parent, "port"); - - if (port) { - /* Found a port, get an endpoint. */ - endpoint = of_get_next_child(port, NULL); - of_node_put(port); - } else { - endpoint = NULL; - } - - if (!endpoint) - pr_err("%s(): no endpoint nodes specified for %s\n", - __func__, parent->full_name); - of_node_put(node); - } else { - port = of_get_parent(prev); - if (!port) - /* Hm, has someone given us the root node ?... */ - return NULL; - - /* Avoid dropping prev node refcount to 0. */ - of_node_get(prev); - endpoint = of_get_next_child(port, prev); - if (endpoint) { - of_node_put(port); - return endpoint; - } - - /* No more endpoints under this port, try the next one. */ - do { - port = of_get_next_child(parent, port); - if (!port) - return NULL; - } while (of_node_cmp(port->name, "port")); - - /* Pick up the first endpoint in this port. */ - endpoint = of_get_next_child(port, NULL); - of_node_put(port); - } - - return endpoint; -} -EXPORT_SYMBOL(v4l2_of_get_next_endpoint); - -/** - * v4l2_of_get_remote_port_parent() - get remote port's parent node - * @node: pointer to a local endpoint device_node - * - * Return: Remote device node associated with remote endpoint node linked - * to @node. Use of_node_put() on it when done. - */ -struct device_node *v4l2_of_get_remote_port_parent( - const struct device_node *node) -{ - struct device_node *np; - unsigned int depth; - - /* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); - - /* Walk 3 levels up only if there is 'ports' node. */ - for (depth = 3; depth && np; depth--) { - np = of_get_next_parent(np); - if (depth == 2 && of_node_cmp(np->name, "ports")) - break; - } - return np; -} -EXPORT_SYMBOL(v4l2_of_get_remote_port_parent); - -/** - * v4l2_of_get_remote_port() - get remote port node - * @node: pointer to a local endpoint device_node - * - * Return: Remote port node associated with remote endpoint node linked - * to @node. Use of_node_put() on it when done. - */ -struct device_node *v4l2_of_get_remote_port(const struct device_node *node) -{ - struct device_node *np; - - /* Get remote endpoint node. */ - np = of_parse_phandle(node, "remote-endpoint", 0); - if (!np) - return NULL; - return of_get_next_parent(np); -} -EXPORT_SYMBOL(v4l2_of_get_remote_port); diff --git a/drivers/of/base.c b/drivers/of/base.c index 89e888a78899..b2f223fa47e9 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1982,3 +1983,120 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) return NULL; } + +/** + * of_graph_get_next_endpoint() - get next endpoint node + * @parent: pointer to the parent device node + * @prev: previous endpoint node, or NULL to get first + * + * Return: An 'endpoint' node pointer with refcount incremented. Refcount + * of the passed @prev node is not decremented, the caller have to use + * of_node_put() on it when done. + */ +struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *endpoint; + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *node; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + node = of_get_child_by_name(parent, "ports"); + if (node) + parent = node; + + port = of_get_child_by_name(parent, "port"); + + if (port) { + /* Found a port, get an endpoint. */ + endpoint = of_get_next_child(port, NULL); + of_node_put(port); + } else { + endpoint = NULL; + } + + if (!endpoint) + pr_err("%s(): no endpoint nodes specified for %s\n", + __func__, parent->full_name); + of_node_put(node); + } else { + port = of_get_parent(prev); + if (!port) + /* Hm, has someone given us the root node ?... */ + return NULL; + + /* Avoid dropping prev node refcount to 0. */ + of_node_get(prev); + endpoint = of_get_next_child(port, prev); + if (endpoint) { + of_node_put(port); + return endpoint; + } + + /* No more endpoints under this port, try the next one. */ + do { + port = of_get_next_child(parent, port); + if (!port) + return NULL; + } while (of_node_cmp(port->name, "port")); + + /* Pick up the first endpoint in this port. */ + endpoint = of_get_next_child(port, NULL); + of_node_put(port); + } + + return endpoint; +} +EXPORT_SYMBOL(of_graph_get_next_endpoint); + +/** + * of_graph_get_remote_port_parent() - get remote port's parent node + * @node: pointer to a local endpoint device_node + * + * Return: Remote device node associated with remote endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_remote_port_parent( + const struct device_node *node) +{ + struct device_node *np; + unsigned int depth; + + /* Get remote endpoint node. */ + np = of_parse_phandle(node, "remote-endpoint", 0); + + /* Walk 3 levels up only if there is 'ports' node. */ + for (depth = 3; depth && np; depth--) { + np = of_get_next_parent(np); + if (depth == 2 && of_node_cmp(np->name, "ports")) + break; + } + return np; +} +EXPORT_SYMBOL(of_graph_get_remote_port_parent); + +/** + * of_graph_get_remote_port() - get remote port node + * @node: pointer to a local endpoint device_node + * + * Return: Remote port node associated with remote endpoint node linked + * to @node. Use of_node_put() on it when done. + */ +struct device_node *of_graph_get_remote_port(const struct device_node *node) +{ + struct device_node *np; + + /* Get remote endpoint node. */ + np = of_parse_phandle(node, "remote-endpoint", 0); + if (!np) + return NULL; + return of_get_next_parent(np); +} +EXPORT_SYMBOL(of_graph_get_remote_port); diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h new file mode 100644 index 000000000000..3bbeb609a360 --- /dev/null +++ b/include/linux/of_graph.h @@ -0,0 +1,46 @@ +/* + * OF graph binding parsing helpers + * + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki + * + * Copyright (C) 2012 Renesas Electronics Corp. + * Author: Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + */ +#ifndef __LINUX_OF_GRAPH_H +#define __LINUX_OF_GRAPH_H + +#ifdef CONFIG_OF +struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, + struct device_node *previous); +struct device_node *of_graph_get_remote_port_parent( + const struct device_node *node); +struct device_node *of_graph_get_remote_port(const struct device_node *node); +#else + +static inline struct device_node *of_graph_get_next_endpoint( + const struct device_node *parent, + struct device_node *previous) +{ + return NULL; +} + +static inline struct device_node *of_graph_get_remote_port_parent( + const struct device_node *node) +{ + return NULL; +} + +static inline struct device_node *of_graph_get_remote_port( + const struct device_node *node) +{ + return NULL; +} + +#endif /* CONFIG_OF */ + +#endif /* __LINUX_OF_GRAPH_H */ diff --git a/include/media/v4l2-of.h b/include/media/v4l2-of.h index 541cea4122e9..3a49735c56a0 100644 --- a/include/media/v4l2-of.h +++ b/include/media/v4l2-of.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -72,11 +73,6 @@ struct v4l2_of_endpoint { #ifdef CONFIG_OF int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint); -struct device_node *v4l2_of_get_next_endpoint(const struct device_node *parent, - struct device_node *previous); -struct device_node *v4l2_of_get_remote_port_parent( - const struct device_node *node); -struct device_node *v4l2_of_get_remote_port(const struct device_node *node); #else /* CONFIG_OF */ static inline int v4l2_of_parse_endpoint(const struct device_node *node, @@ -85,25 +81,6 @@ static inline int v4l2_of_parse_endpoint(const struct device_node *node, return -ENOSYS; } -static inline struct device_node *v4l2_of_get_next_endpoint( - const struct device_node *parent, - struct device_node *previous) -{ - return NULL; -} - -static inline struct device_node *v4l2_of_get_remote_port_parent( - const struct device_node *node) -{ - return NULL; -} - -static inline struct device_node *v4l2_of_get_remote_port( - const struct device_node *node) -{ - return NULL; -} - #endif /* CONFIG_OF */ #endif /* _V4L2_OF_H */ -- cgit v1.2.3 From f2a575f67695dcba9062acd666ae5aab2380b95c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 14 Feb 2014 11:53:56 +0100 Subject: [media] of: move common endpoint parsing to drivers/of This patch adds a new struct of_endpoint which is then embedded in struct v4l2_of_endpoint and contains the endpoint properties that are not V4L2 (or even media) specific: the port number, endpoint id, local device tree node and remote endpoint phandle. of_graph_parse_endpoint parses those properties and is used by v4l2_of_parse_endpoint, which just adds the V4L2 MBUS information to the containing v4l2_of_endpoint structure. Signed-off-by: Philipp Zabel Acked-by: Tomi Valkeinen Acked-by: Mauro Carvalho Chehab Acked-by: Sylwester Nawrocki --- drivers/media/platform/exynos4-is/media-dev.c | 10 +++++----- drivers/media/platform/exynos4-is/mipi-csis.c | 2 +- drivers/media/v4l2-core/v4l2-of.c | 16 +++------------ drivers/of/base.c | 28 +++++++++++++++++++++++++++ include/linux/of_graph.h | 20 +++++++++++++++++++ include/media/v4l2-of.h | 8 ++------ 6 files changed, 59 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index d0f82da59ac5..04d6ecdd314c 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -469,10 +469,10 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, return 0; v4l2_of_parse_endpoint(ep, &endpoint); - if (WARN_ON(endpoint.port == 0) || index >= FIMC_MAX_SENSORS) + if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) return -EINVAL; - pd->mux_id = (endpoint.port - 1) & 0x1; + pd->mux_id = (endpoint.base.port - 1) & 0x1; rem = of_graph_get_remote_port_parent(ep); of_node_put(ep); @@ -494,13 +494,13 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, return -EINVAL; } - if (fimc_input_is_parallel(endpoint.port)) { + if (fimc_input_is_parallel(endpoint.base.port)) { if (endpoint.bus_type == V4L2_MBUS_PARALLEL) pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_601; else pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_656; pd->flags = endpoint.bus.parallel.flags; - } else if (fimc_input_is_mipi_csi(endpoint.port)) { + } else if (fimc_input_is_mipi_csi(endpoint.base.port)) { /* * MIPI CSI-2: only input mux selection and * the sensor's clock frequency is needed. @@ -508,7 +508,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, pd->sensor_bus_type = FIMC_BUS_TYPE_MIPI_CSI2; } else { v4l2_err(&fmd->v4l2_dev, "Wrong port id (%u) at node %s\n", - endpoint.port, rem->full_name); + endpoint.base.port, rem->full_name); } /* * For FIMC-IS handled sensors, that are placed under i2c-isp device diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index fd1ae6549607..3678ba59725c 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -772,7 +772,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, /* Get port node and validate MIPI-CSI channel id. */ v4l2_of_parse_endpoint(node, &endpoint); - state->index = endpoint.port - FIMC_INPUT_MIPI_CSI2_0; + state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES) return -ENXIO; diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index f919db358bbe..b4ed9a955fbe 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -127,17 +127,9 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) { - struct device_node *port_node = of_get_parent(node); - - memset(endpoint, 0, offsetof(struct v4l2_of_endpoint, head)); - - endpoint->local_node = node; - /* - * It doesn't matter whether the two calls below succeed. - * If they don't then the default value 0 is used. - */ - of_property_read_u32(port_node, "reg", &endpoint->port); - of_property_read_u32(node, "reg", &endpoint->id); + of_graph_parse_endpoint(node, &endpoint->base); + endpoint->bus_type = 0; + memset(&endpoint->bus, 0, sizeof(endpoint->bus)); v4l2_of_parse_csi_bus(node, endpoint); /* @@ -147,8 +139,6 @@ int v4l2_of_parse_endpoint(const struct device_node *node, if (endpoint->bus.mipi_csi2.flags == 0) v4l2_of_parse_parallel_bus(node, endpoint); - of_node_put(port_node); - return 0; } EXPORT_SYMBOL(v4l2_of_parse_endpoint); diff --git a/drivers/of/base.c b/drivers/of/base.c index a8e47d37cc7f..715144af3a83 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1984,6 +1984,34 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) return NULL; } +/** + * of_graph_parse_endpoint() - parse common endpoint node properties + * @node: pointer to endpoint device_node + * @endpoint: pointer to the OF endpoint data structure + * + * The caller should hold a reference to @node. + */ +int of_graph_parse_endpoint(const struct device_node *node, + struct of_endpoint *endpoint) +{ + struct device_node *port_node = of_get_parent(node); + + memset(endpoint, 0, sizeof(*endpoint)); + + endpoint->local_node = node; + /* + * It doesn't matter whether the two calls below succeed. + * If they don't then the default value 0 is used. + */ + of_property_read_u32(port_node, "reg", &endpoint->port); + of_property_read_u32(node, "reg", &endpoint->id); + + of_node_put(port_node); + + return 0; +} +EXPORT_SYMBOL(of_graph_parse_endpoint); + /** * of_graph_get_next_endpoint() - get next endpoint node * @parent: pointer to the parent device node diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 3bbeb609a360..2b233db76237 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -14,7 +14,21 @@ #ifndef __LINUX_OF_GRAPH_H #define __LINUX_OF_GRAPH_H +/** + * struct of_endpoint - the OF graph endpoint data structure + * @port: identifier (value of reg property) of a port this endpoint belongs to + * @id: identifier (value of reg property) of this endpoint + * @local_node: pointer to device_node of this endpoint + */ +struct of_endpoint { + unsigned int port; + unsigned int id; + const struct device_node *local_node; +}; + #ifdef CONFIG_OF +int of_graph_parse_endpoint(const struct device_node *node, + struct of_endpoint *endpoint); struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, struct device_node *previous); struct device_node *of_graph_get_remote_port_parent( @@ -22,6 +36,12 @@ struct device_node *of_graph_get_remote_port_parent( struct device_node *of_graph_get_remote_port(const struct device_node *node); #else +static inline int of_graph_parse_endpoint(const struct device_node *node, + struct of_endpoint *endpoint); +{ + return -ENOSYS; +} + static inline struct device_node *of_graph_get_next_endpoint( const struct device_node *parent, struct device_node *previous) diff --git a/include/media/v4l2-of.h b/include/media/v4l2-of.h index 3a49735c56a0..70fa7b7b0487 100644 --- a/include/media/v4l2-of.h +++ b/include/media/v4l2-of.h @@ -51,17 +51,13 @@ struct v4l2_of_bus_parallel { /** * struct v4l2_of_endpoint - the endpoint data structure - * @port: identifier (value of reg property) of a port this endpoint belongs to - * @id: identifier (value of reg property) of this endpoint - * @local_node: pointer to device_node of this endpoint + * @base: struct of_endpoint containing port, id, and local of_node * @bus_type: bus type * @bus: bus configuration data structure * @head: list head for this structure */ struct v4l2_of_endpoint { - unsigned int port; - unsigned int id; - const struct device_node *local_node; + struct of_endpoint base; enum v4l2_mbus_type bus_type; union { struct v4l2_of_bus_parallel parallel; -- cgit v1.2.3 From 00fd9619120db1d6a19be2f9e3df6f76234b311b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 7 Mar 2014 15:49:54 +0100 Subject: of: Fix of_graph_parse_endpoint stub for !CONFIG_OF builds This patch fixes the following build error: In file included from drivers/media/i2c/adv7343.c:29:0: >> include/linux/of_graph.h:41:1: error: expected identifier or '(' before '{' token { ^ include/linux/of_graph.h:39:19: warning: 'of_graph_parse_endpoint' declared 'static' but never defined [-Wunused-function] static inline int of_graph_parse_endpoint(const struct device_node *node, ^ vim +41 include/linux/of_graph.h 35 const struct device_node *node); 36 struct device_node *of_graph_get_remote_port(const struct device_node *node); 37 #else 38 39 static inline int of_graph_parse_endpoint(const struct device_node *node, 40 struct of_endpoint *endpoint); > 41 { 42 return -ENOSYS; 43 } 44 Reported-by: kbuild test robot Signed-off-by: Philipp Zabel --- include/linux/of_graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h index 2b233db76237..befef42e015b 100644 --- a/include/linux/of_graph.h +++ b/include/linux/of_graph.h @@ -37,7 +37,7 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node); #else static inline int of_graph_parse_endpoint(const struct device_node *node, - struct of_endpoint *endpoint); + struct of_endpoint *endpoint) { return -ENOSYS; } -- cgit v1.2.3 From 6080cd0e9239469524d2aa07250ad4b9f383960d Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Sat, 8 Mar 2014 14:53:34 +0200 Subject: staging: usbip: claim ports used by shared devices A device should not be able to be used concurrently both by the server and the client. Claiming the port used by the shared device ensures no interface drivers bind to it and that it is not usable from the server. Signed-off-by: Valentina Manea Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_dev.c | 22 ++++++++++++++++++++++ drivers/usb/core/hub.c | 2 ++ drivers/usb/core/usb.h | 4 ---- include/linux/usb.h | 7 +++++++ 4 files changed, 31 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index ee899f01c008..952743c752d7 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -339,6 +339,7 @@ static int stub_probe(struct usb_device *udev) const char *udev_busid = dev_name(&udev->dev); int err = 0; struct bus_id_priv *busid_priv; + int rc; dev_dbg(&udev->dev, "Enter\n"); @@ -388,6 +389,18 @@ static int stub_probe(struct usb_device *udev) busid_priv->sdev = sdev; busid_priv->udev = udev; + /* + * Claim this hub port. + * It doesn't matter what value we pass as owner + * (struct dev_state) as long as it is unique. + */ + rc = usb_hub_claim_port(udev->parent, udev->portnum, + (struct dev_state *) udev); + if (rc) { + dev_dbg(&udev->dev, "unable to claim port\n"); + return rc; + } + err = stub_add_files(&udev->dev); if (err) { dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); @@ -424,6 +437,7 @@ static void stub_disconnect(struct usb_device *udev) struct stub_device *sdev; const char *udev_busid = dev_name(&udev->dev); struct bus_id_priv *busid_priv; + int rc; dev_dbg(&udev->dev, "Enter\n"); @@ -448,6 +462,14 @@ static void stub_disconnect(struct usb_device *udev) */ stub_remove_files(&udev->dev); + /* release port */ + rc = usb_hub_release_port(udev->parent, udev->portnum, + (struct dev_state *) udev); + if (rc) { + dev_dbg(&udev->dev, "unable to release port\n"); + return; + } + /* If usb reset is called from event handler */ if (busid_priv->sdev->ud.eh == current) return; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 64ea21971be2..e4849333c8de 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1819,6 +1819,7 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, *powner = owner; return rc; } +EXPORT_SYMBOL_GPL(usb_hub_claim_port); int usb_hub_release_port(struct usb_device *hdev, unsigned port1, struct dev_state *owner) @@ -1834,6 +1835,7 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, *powner = NULL; return rc; } +EXPORT_SYMBOL_GPL(usb_hub_release_port); void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) { diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 823857767a16..222bbd2618f1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -57,10 +57,6 @@ extern int usb_match_device(struct usb_device *dev, extern void usb_forced_unbind_intf(struct usb_interface *intf); extern void usb_rebind_intf(struct usb_interface *intf); -extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, - struct dev_state *owner); -extern int usb_hub_release_port(struct usb_device *hdev, unsigned port, - struct dev_state *owner); extern void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner); extern bool usb_device_is_owned(struct usb_device *udev); diff --git a/include/linux/usb.h b/include/linux/usb.h index 22de4affe9c8..140a6a3e7d56 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -366,6 +366,8 @@ struct usb_bus { #endif }; +struct dev_state; + /* ----------------------------------------------------------------------- */ struct usb_tt; @@ -749,6 +751,11 @@ extern struct usb_host_interface *usb_find_alt_setting( unsigned int iface_num, unsigned int alt_num); +/* port claiming functions */ +int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, + struct dev_state *owner); +int usb_hub_release_port(struct usb_device *hdev, unsigned port1, + struct dev_state *owner); /** * usb_make_path - returns stable device path in the usb tree -- cgit v1.2.3 From 9b6f0c4b98171f2a354e1e461fefa90ec2baafa6 Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Mon, 10 Mar 2014 10:36:40 +0200 Subject: usbcore: rename struct dev_state to struct usb_dev_state Since it is needed outside usbcore and exposed in include/linux/usb.h, it conflicts with enum dev_state in rt2x00 wireless driver. Mark it as usb specific to avoid conflicts in the future. Signed-off-by: Valentina Manea Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/stub_dev.c | 4 +- drivers/usb/core/devio.c | 112 +++++++++++++++++++-------------------- drivers/usb/core/hub.c | 12 ++--- drivers/usb/core/hub.h | 2 +- drivers/usb/core/usb.h | 4 +- include/linux/usb.h | 6 +-- 6 files changed, 70 insertions(+), 70 deletions(-) (limited to 'include') diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index 952743c752d7..773d8ca07a00 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -395,7 +395,7 @@ static int stub_probe(struct usb_device *udev) * (struct dev_state) as long as it is unique. */ rc = usb_hub_claim_port(udev->parent, udev->portnum, - (struct dev_state *) udev); + (struct usb_dev_state *) udev); if (rc) { dev_dbg(&udev->dev, "unable to claim port\n"); return rc; @@ -464,7 +464,7 @@ static void stub_disconnect(struct usb_device *udev) /* release port */ rc = usb_hub_release_port(udev->parent, udev->portnum, - (struct dev_state *) udev); + (struct usb_dev_state *) udev); if (rc) { dev_dbg(&udev->dev, "unable to release port\n"); return; diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 90e18f6fa2bb..2a8afe6754b8 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -62,7 +62,7 @@ /* Mutual exclusion for removal, open, and release */ DEFINE_MUTEX(usbfs_mutex); -struct dev_state { +struct usb_dev_state { struct list_head list; /* state list */ struct usb_device *dev; struct file *file; @@ -81,7 +81,7 @@ struct dev_state { struct async { struct list_head asynclist; - struct dev_state *ps; + struct usb_dev_state *ps; struct pid *pid; const struct cred *cred; unsigned int signr; @@ -151,7 +151,7 @@ static void usbfs_decrease_memory_usage(unsigned amount) atomic_sub(amount, &usbfs_memory_usage); } -static int connected(struct dev_state *ps) +static int connected(struct usb_dev_state *ps) { return (!list_empty(&ps->list) && ps->dev->state != USB_STATE_NOTATTACHED); @@ -184,7 +184,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct dev_state *ps = file->private_data; + struct usb_dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; ssize_t ret = 0; unsigned len; @@ -307,7 +307,7 @@ static void free_async(struct async *as) static void async_newpending(struct async *as) { - struct dev_state *ps = as->ps; + struct usb_dev_state *ps = as->ps; unsigned long flags; spin_lock_irqsave(&ps->lock, flags); @@ -317,7 +317,7 @@ static void async_newpending(struct async *as) static void async_removepending(struct async *as) { - struct dev_state *ps = as->ps; + struct usb_dev_state *ps = as->ps; unsigned long flags; spin_lock_irqsave(&ps->lock, flags); @@ -325,7 +325,7 @@ static void async_removepending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static struct async *async_getcompleted(struct dev_state *ps) +static struct async *async_getcompleted(struct usb_dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -340,7 +340,7 @@ static struct async *async_getcompleted(struct dev_state *ps) return as; } -static struct async *async_getpending(struct dev_state *ps, +static struct async *async_getpending(struct usb_dev_state *ps, void __user *userurb) { struct async *as; @@ -448,7 +448,7 @@ static int copy_urb_data_to_user(u8 __user *userbuffer, struct urb *urb) #define AS_CONTINUATION 1 #define AS_UNLINK 2 -static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr) +static void cancel_bulk_urbs(struct usb_dev_state *ps, unsigned bulk_addr) __releases(ps->lock) __acquires(ps->lock) { @@ -489,7 +489,7 @@ __acquires(ps->lock) static void async_completed(struct urb *urb) { struct async *as = urb->context; - struct dev_state *ps = as->ps; + struct usb_dev_state *ps = as->ps; struct siginfo sinfo; struct pid *pid = NULL; u32 secid = 0; @@ -529,7 +529,7 @@ static void async_completed(struct urb *urb) wake_up(&ps->wait); } -static void destroy_async(struct dev_state *ps, struct list_head *list) +static void destroy_async(struct usb_dev_state *ps, struct list_head *list) { struct urb *urb; struct async *as; @@ -551,7 +551,7 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) spin_unlock_irqrestore(&ps->lock, flags); } -static void destroy_async_on_interface(struct dev_state *ps, +static void destroy_async_on_interface(struct usb_dev_state *ps, unsigned int ifnum) { struct list_head *p, *q, hitlist; @@ -566,7 +566,7 @@ static void destroy_async_on_interface(struct dev_state *ps, destroy_async(ps, &hitlist); } -static void destroy_all_async(struct dev_state *ps) +static void destroy_all_async(struct usb_dev_state *ps) { destroy_async(ps, &ps->async_pending); } @@ -585,7 +585,7 @@ static int driver_probe(struct usb_interface *intf, static void driver_disconnect(struct usb_interface *intf) { - struct dev_state *ps = usb_get_intfdata(intf); + struct usb_dev_state *ps = usb_get_intfdata(intf); unsigned int ifnum = intf->altsetting->desc.bInterfaceNumber; if (!ps) @@ -628,7 +628,7 @@ struct usb_driver usbfs_driver = { .resume = driver_resume, }; -static int claimintf(struct dev_state *ps, unsigned int ifnum) +static int claimintf(struct usb_dev_state *ps, unsigned int ifnum) { struct usb_device *dev = ps->dev; struct usb_interface *intf; @@ -650,7 +650,7 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum) return err; } -static int releaseintf(struct dev_state *ps, unsigned int ifnum) +static int releaseintf(struct usb_dev_state *ps, unsigned int ifnum) { struct usb_device *dev; struct usb_interface *intf; @@ -670,7 +670,7 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) return err; } -static int checkintf(struct dev_state *ps, unsigned int ifnum) +static int checkintf(struct usb_dev_state *ps, unsigned int ifnum) { if (ps->dev->state != USB_STATE_CONFIGURED) return -EHOSTUNREACH; @@ -710,7 +710,7 @@ static int findintfep(struct usb_device *dev, unsigned int ep) return -ENOENT; } -static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, +static int check_ctrlrecip(struct usb_dev_state *ps, unsigned int requesttype, unsigned int request, unsigned int index) { int ret = 0; @@ -791,11 +791,11 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt) static int usbdev_open(struct inode *inode, struct file *file) { struct usb_device *dev = NULL; - struct dev_state *ps; + struct usb_dev_state *ps; int ret; ret = -ENOMEM; - ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL); + ps = kmalloc(sizeof(struct usb_dev_state), GFP_KERNEL); if (!ps) goto out_free_ps; @@ -852,7 +852,7 @@ static int usbdev_open(struct inode *inode, struct file *file) static int usbdev_release(struct inode *inode, struct file *file) { - struct dev_state *ps = file->private_data; + struct usb_dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; struct async *as; @@ -883,7 +883,7 @@ static int usbdev_release(struct inode *inode, struct file *file) return 0; } -static int proc_control(struct dev_state *ps, void __user *arg) +static int proc_control(struct usb_dev_state *ps, void __user *arg) { struct usb_device *dev = ps->dev; struct usbdevfs_ctrltransfer ctrl; @@ -970,7 +970,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) return ret; } -static int proc_bulk(struct dev_state *ps, void __user *arg) +static int proc_bulk(struct usb_dev_state *ps, void __user *arg) { struct usb_device *dev = ps->dev; struct usbdevfs_bulktransfer bulk; @@ -1043,7 +1043,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) return ret; } -static int proc_resetep(struct dev_state *ps, void __user *arg) +static int proc_resetep(struct usb_dev_state *ps, void __user *arg) { unsigned int ep; int ret; @@ -1060,7 +1060,7 @@ static int proc_resetep(struct dev_state *ps, void __user *arg) return 0; } -static int proc_clearhalt(struct dev_state *ps, void __user *arg) +static int proc_clearhalt(struct usb_dev_state *ps, void __user *arg) { unsigned int ep; int pipe; @@ -1082,7 +1082,7 @@ static int proc_clearhalt(struct dev_state *ps, void __user *arg) return usb_clear_halt(ps->dev, pipe); } -static int proc_getdriver(struct dev_state *ps, void __user *arg) +static int proc_getdriver(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_getdriver gd; struct usb_interface *intf; @@ -1101,7 +1101,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) return ret; } -static int proc_connectinfo(struct dev_state *ps, void __user *arg) +static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_connectinfo ci = { .devnum = ps->dev->devnum, @@ -1113,12 +1113,12 @@ static int proc_connectinfo(struct dev_state *ps, void __user *arg) return 0; } -static int proc_resetdevice(struct dev_state *ps) +static int proc_resetdevice(struct usb_dev_state *ps) { return usb_reset_device(ps->dev); } -static int proc_setintf(struct dev_state *ps, void __user *arg) +static int proc_setintf(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_setinterface setintf; int ret; @@ -1131,7 +1131,7 @@ static int proc_setintf(struct dev_state *ps, void __user *arg) setintf.altsetting); } -static int proc_setconfig(struct dev_state *ps, void __user *arg) +static int proc_setconfig(struct usb_dev_state *ps, void __user *arg) { int u; int status = 0; @@ -1179,7 +1179,7 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg) return status; } -static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, +static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb, struct usbdevfs_iso_packet_desc __user *iso_frame_desc, void __user *arg) { @@ -1508,7 +1508,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return ret; } -static int proc_submiturb(struct dev_state *ps, void __user *arg) +static int proc_submiturb(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_urb uurb; @@ -1520,7 +1520,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) arg); } -static int proc_unlinkurb(struct dev_state *ps, void __user *arg) +static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg) { struct urb *urb; struct async *as; @@ -1580,7 +1580,7 @@ err_out: return -EFAULT; } -static struct async *reap_as(struct dev_state *ps) +static struct async *reap_as(struct usb_dev_state *ps) { DECLARE_WAITQUEUE(wait, current); struct async *as = NULL; @@ -1603,7 +1603,7 @@ static struct async *reap_as(struct dev_state *ps) return as; } -static int proc_reapurb(struct dev_state *ps, void __user *arg) +static int proc_reapurb(struct usb_dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); if (as) { @@ -1616,7 +1616,7 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg) return -EIO; } -static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) +static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) { int retval; struct async *as; @@ -1631,7 +1631,7 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg) } #ifdef CONFIG_COMPAT -static int proc_control_compat(struct dev_state *ps, +static int proc_control_compat(struct usb_dev_state *ps, struct usbdevfs_ctrltransfer32 __user *p32) { struct usbdevfs_ctrltransfer __user *p; @@ -1644,7 +1644,7 @@ static int proc_control_compat(struct dev_state *ps, return proc_control(ps, p); } -static int proc_bulk_compat(struct dev_state *ps, +static int proc_bulk_compat(struct usb_dev_state *ps, struct usbdevfs_bulktransfer32 __user *p32) { struct usbdevfs_bulktransfer __user *p; @@ -1661,7 +1661,7 @@ static int proc_bulk_compat(struct dev_state *ps, return proc_bulk(ps, p); } -static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg) +static int proc_disconnectsignal_compat(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_disconnectsignal32 ds; @@ -1699,7 +1699,7 @@ static int get_urb32(struct usbdevfs_urb *kurb, return 0; } -static int proc_submiturb_compat(struct dev_state *ps, void __user *arg) +static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_urb uurb; @@ -1745,7 +1745,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) return 0; } -static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) +static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg) { struct async *as = reap_as(ps); if (as) { @@ -1758,7 +1758,7 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg) return -EIO; } -static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) +static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *arg) { int retval; struct async *as; @@ -1775,7 +1775,7 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg) #endif -static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) +static int proc_disconnectsignal(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_disconnectsignal ds; @@ -1786,7 +1786,7 @@ static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) return 0; } -static int proc_claiminterface(struct dev_state *ps, void __user *arg) +static int proc_claiminterface(struct usb_dev_state *ps, void __user *arg) { unsigned int ifnum; @@ -1795,7 +1795,7 @@ static int proc_claiminterface(struct dev_state *ps, void __user *arg) return claimintf(ps, ifnum); } -static int proc_releaseinterface(struct dev_state *ps, void __user *arg) +static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg) { unsigned int ifnum; int ret; @@ -1808,7 +1808,7 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg) return 0; } -static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) +static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) { int size; void *buf = NULL; @@ -1884,7 +1884,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) return retval; } -static int proc_ioctl_default(struct dev_state *ps, void __user *arg) +static int proc_ioctl_default(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_ioctl ctrl; @@ -1894,7 +1894,7 @@ static int proc_ioctl_default(struct dev_state *ps, void __user *arg) } #ifdef CONFIG_COMPAT -static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) +static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg) { struct usbdevfs_ioctl32 __user *uioc; struct usbdevfs_ioctl ctrl; @@ -1912,7 +1912,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) } #endif -static int proc_claim_port(struct dev_state *ps, void __user *arg) +static int proc_claim_port(struct usb_dev_state *ps, void __user *arg) { unsigned portnum; int rc; @@ -1926,7 +1926,7 @@ static int proc_claim_port(struct dev_state *ps, void __user *arg) return rc; } -static int proc_release_port(struct dev_state *ps, void __user *arg) +static int proc_release_port(struct usb_dev_state *ps, void __user *arg) { unsigned portnum; @@ -1935,7 +1935,7 @@ static int proc_release_port(struct dev_state *ps, void __user *arg) return usb_hub_release_port(ps->dev, portnum, ps); } -static int proc_get_capabilities(struct dev_state *ps, void __user *arg) +static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) { __u32 caps; @@ -1951,7 +1951,7 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg) return 0; } -static int proc_disconnect_claim(struct dev_state *ps, void __user *arg) +static int proc_disconnect_claim(struct usb_dev_state *ps, void __user *arg) { struct usbdevfs_disconnect_claim dc; struct usb_interface *intf; @@ -1991,7 +1991,7 @@ static int proc_disconnect_claim(struct dev_state *ps, void __user *arg) static long usbdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p) { - struct dev_state *ps = file->private_data; + struct usb_dev_state *ps = file->private_data; struct inode *inode = file_inode(file); struct usb_device *dev = ps->dev; int ret = -ENOTTY; @@ -2192,7 +2192,7 @@ static long usbdev_compat_ioctl(struct file *file, unsigned int cmd, static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait) { - struct dev_state *ps = file->private_data; + struct usb_dev_state *ps = file->private_data; unsigned int mask = 0; poll_wait(file, &ps->wait, wait); @@ -2218,11 +2218,11 @@ const struct file_operations usbdev_file_operations = { static void usbdev_remove(struct usb_device *udev) { - struct dev_state *ps; + struct usb_dev_state *ps; struct siginfo sinfo; while (!list_empty(&udev->filelist)) { - ps = list_entry(udev->filelist.next, struct dev_state, list); + ps = list_entry(udev->filelist.next, struct usb_dev_state, list); destroy_all_async(ps); wake_up_all(&ps->wait); list_del_init(&ps->list); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e4849333c8de..be6e02e91f56 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1788,7 +1788,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) * to one of these "claimed" ports, the program will "own" the device. */ static int find_port_owner(struct usb_device *hdev, unsigned port1, - struct dev_state ***ppowner) + struct usb_dev_state ***ppowner) { struct usb_hub *hub = usb_hub_to_struct_hub(hdev); @@ -1806,10 +1806,10 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, /* In the following three functions, the caller must hold hdev's lock */ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, - struct dev_state *owner) + struct usb_dev_state *owner) { int rc; - struct dev_state **powner; + struct usb_dev_state **powner; rc = find_port_owner(hdev, port1, &powner); if (rc) @@ -1822,10 +1822,10 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, EXPORT_SYMBOL_GPL(usb_hub_claim_port); int usb_hub_release_port(struct usb_device *hdev, unsigned port1, - struct dev_state *owner) + struct usb_dev_state *owner) { int rc; - struct dev_state **powner; + struct usb_dev_state **powner; rc = find_port_owner(hdev, port1, &powner); if (rc) @@ -1837,7 +1837,7 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, } EXPORT_SYMBOL_GPL(usb_hub_release_port); -void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) +void usb_hub_release_all_ports(struct usb_device *hdev, struct usb_dev_state *owner) { struct usb_hub *hub = usb_hub_to_struct_hub(hdev); int n; diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index df629a310e44..33bcb2c6f90a 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -89,7 +89,7 @@ struct usb_hub { struct usb_port { struct usb_device *child; struct device dev; - struct dev_state *port_owner; + struct usb_dev_state *port_owner; enum usb_port_connect_type connect_type; u8 portnum; unsigned power_is_on:1; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 222bbd2618f1..a87532845bf9 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -2,7 +2,7 @@ #include struct usb_hub_descriptor; -struct dev_state; +struct usb_dev_state; /* Functions local to drivers/usb/core/ */ @@ -58,7 +58,7 @@ extern void usb_forced_unbind_intf(struct usb_interface *intf); extern void usb_rebind_intf(struct usb_interface *intf); extern void usb_hub_release_all_ports(struct usb_device *hdev, - struct dev_state *owner); + struct usb_dev_state *owner); extern bool usb_device_is_owned(struct usb_device *udev); extern int usb_hub_init(void); diff --git a/include/linux/usb.h b/include/linux/usb.h index 140a6a3e7d56..b55600a1edc3 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -366,7 +366,7 @@ struct usb_bus { #endif }; -struct dev_state; +struct usb_dev_state; /* ----------------------------------------------------------------------- */ @@ -753,9 +753,9 @@ extern struct usb_host_interface *usb_find_alt_setting( /* port claiming functions */ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, - struct dev_state *owner); + struct usb_dev_state *owner); int usb_hub_release_port(struct usb_device *hdev, unsigned port1, - struct dev_state *owner); + struct usb_dev_state *owner); /** * usb_make_path - returns stable device path in the usb tree -- cgit v1.2.3