at v5.3 3.1 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 = sprintf(buf, "%16ph\n", wusb_dev->cdid.data); 54 wusb_dev_put(wusb_dev); 55 return result; 56} 57static DEVICE_ATTR_RO(wusb_cdid); 58 59static ssize_t wusb_ck_store(struct device *dev, 60 struct device_attribute *attr, 61 const char *buf, size_t size) 62{ 63 int result; 64 struct usb_device *usb_dev; 65 struct wusbhc *wusbhc; 66 struct wusb_ckhdid ck; 67 68 result = sscanf(buf, 69 "%02hhx %02hhx %02hhx %02hhx " 70 "%02hhx %02hhx %02hhx %02hhx " 71 "%02hhx %02hhx %02hhx %02hhx " 72 "%02hhx %02hhx %02hhx %02hhx\n", 73 &ck.data[0] , &ck.data[1], 74 &ck.data[2] , &ck.data[3], 75 &ck.data[4] , &ck.data[5], 76 &ck.data[6] , &ck.data[7], 77 &ck.data[8] , &ck.data[9], 78 &ck.data[10], &ck.data[11], 79 &ck.data[12], &ck.data[13], 80 &ck.data[14], &ck.data[15]); 81 if (result != 16) 82 return -EINVAL; 83 84 usb_dev = to_usb_device(dev); 85 wusbhc = wusbhc_get_by_usb_dev(usb_dev); 86 if (wusbhc == NULL) 87 return -ENODEV; 88 result = wusb_dev_4way_handshake(wusbhc, usb_dev->wusb_dev, &ck); 89 memzero_explicit(&ck, sizeof(ck)); 90 wusbhc_put(wusbhc); 91 return result < 0 ? result : size; 92} 93static DEVICE_ATTR_WO(wusb_ck); 94 95static struct attribute *wusb_dev_attrs[] = { 96 &dev_attr_wusb_disconnect.attr, 97 &dev_attr_wusb_cdid.attr, 98 &dev_attr_wusb_ck.attr, 99 NULL, 100}; 101 102static const struct attribute_group wusb_dev_attr_group = { 103 .name = NULL, /* we want them in the same directory */ 104 .attrs = wusb_dev_attrs, 105}; 106 107int wusb_dev_sysfs_add(struct wusbhc *wusbhc, struct usb_device *usb_dev, 108 struct wusb_dev *wusb_dev) 109{ 110 int result = sysfs_create_group(&usb_dev->dev.kobj, 111 &wusb_dev_attr_group); 112 struct device *dev = &usb_dev->dev; 113 if (result < 0) 114 dev_err(dev, "Cannot register WUSB-dev attributes: %d\n", 115 result); 116 return result; 117} 118 119void wusb_dev_sysfs_rm(struct wusb_dev *wusb_dev) 120{ 121 struct usb_device *usb_dev = wusb_dev->usb_dev; 122 if (usb_dev) 123 sysfs_remove_group(&usb_dev->dev.kobj, &wusb_dev_attr_group); 124}