2 * drivers/net/can/softing/softing_sysfs.c
6 * - Kurt Van Dijck, EIA Electronics
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the version 2 of the GNU General Public License
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/version.h>
23 #include <linux/module.h>
24 #include <linux/device.h>
25 #include <linux/mutex.h>
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
30 #error This driver does not support Kernel versions < 2.6.23
35 /* Because the struct softing may be used by pcmcia devices
36 * as well as pci devices, * we have no clue how to get
37 * from a struct device * towards the struct softing *.
38 * It may go over a pci_device->priv or over a pcmcia_device->priv.
39 * Therefore, provide the struct softing pointer within the attribute.
40 * Then we don't need driver/bus specific things in these attributes
42 struct softing_attribute {
43 struct device_attribute dev;
44 ssize_t (*show) (struct softing *card, char *buf);
45 ssize_t (*store)(struct softing *card, const char *buf, size_t count);
49 static ssize_t rd_card_attr(struct device *dev, struct device_attribute *attr
51 struct softing_attribute *cattr
52 = container_of(attr, struct softing_attribute, dev);
53 return cattr->show ? cattr->show(cattr->card, buf) : 0;
55 static ssize_t wr_card_attr(struct device *dev, struct device_attribute *attr
56 , const char *buf, size_t count) {
57 struct softing_attribute *cattr
58 = container_of(attr, struct softing_attribute, dev);
59 return cattr->store ? cattr->store(cattr->card, buf, count) : 0;
62 #define declare_attr(_name, _mode, _show, _store) { \
65 .name = __stringify(_name), \
68 .show = rd_card_attr, \
69 .store = wr_card_attr, \
75 #define CARD_SHOW(name, member) \
76 static ssize_t show_##name(struct softing *card, char *buf) { \
77 return sprintf(buf, "%u\n", card->member); \
79 CARD_SHOW(serial , id.serial);
80 CARD_SHOW(firmware , id.fw);
81 CARD_SHOW(hardware , id.hw);
82 CARD_SHOW(license , id.lic);
83 CARD_SHOW(freq , id.freq);
84 CARD_SHOW(txpending , tx.pending);
86 static const struct softing_attribute card_attr_proto[] = {
87 declare_attr(serial , 0444, show_serial , 0),
88 declare_attr(firmware , 0444, show_firmware , 0),
89 declare_attr(hardware , 0444, show_hardware , 0),
90 declare_attr(license , 0444, show_license , 0),
91 declare_attr(freq , 0444, show_freq , 0),
92 declare_attr(txpending , 0644, show_txpending , 0),
95 int softing_card_sysfs_create(struct softing *card)
100 size = sizeof(card_attr_proto)/sizeof(card_attr_proto[0]);
101 card->attr = kmalloc((size+1)*sizeof(card->attr[0]), GFP_KERNEL);
103 goto attr_mem_failed;
104 memcpy(card->attr, card_attr_proto, size * sizeof(card->attr[0]));
105 memset(&card->attr[size], 0, sizeof(card->attr[0]));
107 card->grp = kmalloc((size+1)*sizeof(card->grp[0]), GFP_KERNEL);
111 for (j = 0; j < size; ++j) {
112 card->attr[j].card = card;
113 card->grp[j] = &card->attr[j].dev.attr;
114 if (!card->attr[j].show)
115 card->attr[j].dev.attr.mode &= ~(S_IRUGO);
116 if (!card->attr[j].store)
117 card->attr[j].dev.attr.mode &= ~(S_IWUGO);
120 card->sysfs.name = "softing";
121 card->sysfs.attrs = card->grp;
122 if (sysfs_create_group(&card->dev->kobj, &card->sysfs) < 0)
134 void softing_card_sysfs_remove(struct softing *card)
136 sysfs_remove_group(&card->dev->kobj, &card->sysfs);
141 static ssize_t show_channel(struct device *dev
142 , struct device_attribute *attr, char *buf)
144 struct net_device *ndev = to_net_dev(dev);
145 struct softing_priv *priv = netdev2softing(ndev);
146 return sprintf(buf, "%i\n", priv->index);
149 static ssize_t show_chip(struct device *dev
150 , struct device_attribute *attr, char *buf)
152 struct net_device *ndev = to_net_dev(dev);
153 struct softing_priv *priv = netdev2softing(ndev);
154 return sprintf(buf, "%i\n", priv->chip);
157 static ssize_t show_output(struct device *dev
158 , struct device_attribute *attr, char *buf)
160 struct net_device *ndev = to_net_dev(dev);
161 struct softing_priv *priv = netdev2softing(ndev);
162 return sprintf(buf, "0x%02x\n", priv->output);
165 static ssize_t store_output(struct device *dev
166 , struct device_attribute *attr
167 , const char *buf, size_t count)
169 struct net_device *ndev = to_net_dev(dev);
170 struct softing_priv *priv = netdev2softing(ndev);
171 struct softing *card = priv->card;
175 ret = strict_strtoul(buf, 0, &val);
180 ret = mutex_lock_interruptible(&card->fw.lock);
183 if (netif_running(ndev)) {
184 mutex_unlock(&card->fw.lock);
188 mutex_unlock(&card->fw.lock);
192 * the latest softing cards support sleep mode too
195 static const DEVICE_ATTR(channel, S_IRUGO, show_channel, 0);
196 static const DEVICE_ATTR(chip, S_IRUGO, show_chip, 0);
197 static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output);
199 static const struct attribute *const netdev_sysfs_entries[] = {
200 &dev_attr_channel .attr,
201 &dev_attr_chip .attr,
202 &dev_attr_output .attr,
205 static const struct attribute_group netdev_sysfs = {
207 .attrs = (struct attribute **)netdev_sysfs_entries,
210 int softing_bus_sysfs_create(struct softing_priv *priv)
212 if (!priv->netdev->dev.kobj.sd) {
213 dev_alert(priv->card->dev, "sysfs_create_group would fail\n");
216 return sysfs_create_group(&priv->netdev->dev.kobj, &netdev_sysfs);
218 void softing_bus_sysfs_remove(struct softing_priv *priv)
220 sysfs_remove_group(&priv->netdev->dev.kobj, &netdev_sysfs);