at v4.15 3.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * WUSB devices 4 * sysfs bindings 5 * 6 * Copyright (C) 2007 Intel Corporation 7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 8 * 9 * Get them out of the way... 10 */ 11 12#include <linux/jiffies.h> 13#include <linux/ctype.h> 14#include <linux/workqueue.h> 15#include "wusbhc.h" 16 17static ssize_t wusb_disconnect_store(struct device *dev, 18 struct device_attribute *attr, 19 const char *buf, size_t size) 20{ 21 struct usb_device *usb_dev; 22 struct wusbhc *wusbhc; 23 unsigned command; 24 u8 port_idx; 25 26 if (sscanf(buf, "%u", &command) != 1) 27 return -EINVAL; 28 if (command == 0) 29 return size; 30 usb_dev = to_usb_device(dev); 31 wusbhc = wusbhc_get_by_usb_dev(usb_dev); 32 if (wusbhc == NULL) 33 return -ENODEV; 34 35 mutex_lock(&wusbhc->mutex); 36 port_idx = wusb_port_no_to_idx(usb_dev->portnum); 37 __wusbhc_dev_disable(wusbhc, port_idx); 38 mutex_unlock(&wusbhc->mutex); 39 wusbhc_put(wusbhc); 40 return size; 41} 42static DEVICE_ATTR_WO(wusb_disconnect); 43 44static ssize_t wusb_cdid_show(struct device *dev, 45 struct device_attribute *attr, char *buf) 46{ 47 ssize_t result; 48 struct wusb_dev *wusb_dev; 49 50 wusb_dev = wusb_dev_get_by_usb_dev(to_usb_device(dev)); 51 if (wusb_dev == NULL) 52 return -ENODEV; 53 result = ckhdid_printf(buf, PAGE_SIZE, &wusb_dev->cdid); 54 strcat(buf, "\n"); 55 wusb_dev_put(wusb_dev); 56 return result + 1; 57} 58static DEVICE_ATTR_RO(wusb_cdid); 59 60static ssize_t wusb_ck_store(struct device *dev, 61 struct device_attribute *attr, 62 const char *buf, size_t size) 63{ 64 int result; 65 struct usb_device *usb_dev; 66 struct wusbhc *wusbhc; 67 struct wusb_ckhdid ck; 68 69 result = sscanf(buf, 70 "%02hhx %02hhx %02hhx %02hhx " 71 "%02hhx %02hhx %02hhx %02hhx " 72 "%02hhx %02hhx %02hhx %02hhx " 73 "%02hhx %02hhx %02hhx %02hhx\n", 74 &ck.data[0] , &ck.data[1], 75 &ck.data[2] , &ck.data[3], 76 &ck.data[4] , &ck.data[5], 77 &ck.data[6] , &ck.data[7], 78 &ck.data[8] , &ck.data[9], 79 &ck.data[10], &ck.data[11], 80 &ck.data[12], &ck.data[13], 81 &ck.data[14], &ck.data[15]); 82 if (result != 16) 83 return -EINVAL; 84 85 usb_dev = to_usb_device(dev); 86 wusbhc = wusbhc_get_by_usb_dev(usb_dev); 87 if (wusbhc == NULL) 88 return -ENODEV; 89 result = wusb_dev_4way_handshake(wusbhc, usb_dev->wusb_dev, &ck); 90 memzero_explicit(&ck, sizeof(ck)); 91 wusbhc_put(wusbhc); 92 return result < 0 ? result : size; 93} 94static DEVICE_ATTR_WO(wusb_ck); 95 96static struct attribute *wusb_dev_attrs[] = { 97 &dev_attr_wusb_disconnect.attr, 98 &dev_attr_wusb_cdid.attr, 99 &dev_attr_wusb_ck.attr, 100 NULL, 101}; 102 103static const struct attribute_group wusb_dev_attr_group = { 104 .name = NULL, /* we want them in the same directory */ 105 .attrs = wusb_dev_attrs, 106}; 107 108int wusb_dev_sysfs_add(struct wusbhc *wusbhc, struct usb_device *usb_dev, 109 struct wusb_dev *wusb_dev) 110{ 111 int result = sysfs_create_group(&usb_dev->dev.kobj, 112 &wusb_dev_attr_group); 113 struct device *dev = &usb_dev->dev; 114 if (result < 0) 115 dev_err(dev, "Cannot register WUSB-dev attributes: %d\n", 116 result); 117 return result; 118} 119 120void wusb_dev_sysfs_rm(struct wusb_dev *wusb_dev) 121{ 122 struct usb_device *usb_dev = wusb_dev->usb_dev; 123 if (usb_dev) 124 sysfs_remove_group(&usb_dev->dev.kobj, &wusb_dev_attr_group); 125}