Blame view

net/ieee802154/wpan-class.c 5.1 KB
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Copyright (C) 2007, 2008, 2009 Siemens AG
   *
   * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
18
  #include <linux/slab.h>
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
19
20
21
22
23
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/device.h>
  
  #include <net/wpan-phy.h>
cb6b37635   Dmitry Eremin-Solenikov   ieee802154: merge...
24
  #include "ieee802154.h"
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
25
26
27
28
29
30
31
32
  #define MASTER_SHOW_COMPLEX(name, format_string, args...)		\
  static ssize_t name ## _show(struct device *dev,			\
  			    struct device_attribute *attr, char *buf)	\
  {									\
  	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);	\
  	int ret;							\
  									\
  	mutex_lock(&phy->pib_lock);					\
375bb0e04   Dmitry Eremin-Solenikov   wpan-phy: use snp...
33
34
  	ret = snprintf(buf, PAGE_SIZE, format_string "
  ", args);	\
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
35
36
37
38
39
40
41
42
43
  	mutex_unlock(&phy->pib_lock);					\
  	return ret;							\
  }
  
  #define MASTER_SHOW(field, format_string)				\
  	MASTER_SHOW_COMPLEX(field, format_string, phy->field)
  
  MASTER_SHOW(current_channel, "%d");
  MASTER_SHOW(current_page, "%d");
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
44
45
46
47
  MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB",
  	((signed char) (phy->transmit_power << 2)) >> 2,
  	(phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1 );
  MASTER_SHOW(cca_mode, "%d");
a0b4a738e   Dmitry Eremin-Solenikov   wpan-phy: allow s...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  static ssize_t channels_supported_show(struct device *dev,
  			    struct device_attribute *attr, char *buf)
  {
  	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
  	int ret;
  	int i, len = 0;
  
  	mutex_lock(&phy->pib_lock);
  	for (i = 0; i < 32; i++) {
  		ret = snprintf(buf + len, PAGE_SIZE - len,
  				"%#09x
  ", phy->channels_supported[i]);
  		if (ret < 0)
  			break;
  		len += ret;
  	}
  	mutex_unlock(&phy->pib_lock);
  	return len;
  }
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  static struct device_attribute pmib_attrs[] = {
  	__ATTR_RO(current_channel),
  	__ATTR_RO(current_page),
  	__ATTR_RO(channels_supported),
  	__ATTR_RO(transmit_power),
  	__ATTR_RO(cca_mode),
  	{},
  };
  
  static void wpan_phy_release(struct device *d)
  {
  	struct wpan_phy *phy = container_of(d, struct wpan_phy, dev);
  	kfree(phy);
  }
  
  static struct class wpan_phy_class = {
  	.name = "ieee802154",
  	.dev_release = wpan_phy_release,
  	.dev_attrs = pmib_attrs,
  };
  
  static DEFINE_MUTEX(wpan_phy_mutex);
  static int wpan_phy_idx;
  
  static int wpan_phy_match(struct device *dev, void *data)
  {
  	return !strcmp(dev_name(dev), (const char *)data);
  }
  
  struct wpan_phy *wpan_phy_find(const char *str)
  {
  	struct device *dev;
  
  	if (WARN_ON(!str))
  		return NULL;
  
  	dev = class_find_device(&wpan_phy_class, NULL,
  			(void *)str, wpan_phy_match);
  	if (!dev)
  		return NULL;
  
  	return container_of(dev, struct wpan_phy, dev);
  }
  EXPORT_SYMBOL(wpan_phy_find);
1c889f4db   Dmitry Eremin-Solenikov   wpan-phy: add wpa...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  struct wpan_phy_iter_data {
  	int (*fn)(struct wpan_phy *phy, void *data);
  	void *data;
  };
  
  static int wpan_phy_iter(struct device *dev, void *_data)
  {
  	struct wpan_phy_iter_data *wpid = _data;
  	struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
  	return wpid->fn(phy, wpid->data);
  }
  
  int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
  		void *data)
  {
  	struct wpan_phy_iter_data wpid = {
  		.fn = fn,
  		.data = data,
  	};
  
  	return class_for_each_device(&wpan_phy_class, NULL,
  			&wpid, wpan_phy_iter);
  }
  EXPORT_SYMBOL(wpan_phy_for_each);
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
135
136
137
138
139
140
141
142
143
  static int wpan_phy_idx_valid(int idx)
  {
  	return idx >= 0;
  }
  
  struct wpan_phy *wpan_phy_alloc(size_t priv_size)
  {
  	struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size,
  			GFP_KERNEL);
a6c0f8217   Denis Kirjanov   ieee802154: Fix p...
144
145
  	if (!phy)
  		goto out;
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
146
147
148
149
150
151
  	mutex_lock(&wpan_phy_mutex);
  	phy->idx = wpan_phy_idx++;
  	if (unlikely(!wpan_phy_idx_valid(phy->idx))) {
  		wpan_phy_idx--;
  		mutex_unlock(&wpan_phy_mutex);
  		kfree(phy);
a6c0f8217   Denis Kirjanov   ieee802154: Fix p...
152
  		goto out;
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
153
154
155
156
157
158
159
160
161
  	}
  	mutex_unlock(&wpan_phy_mutex);
  
  	mutex_init(&phy->pib_lock);
  
  	device_initialize(&phy->dev);
  	dev_set_name(&phy->dev, "wpan-phy%d", phy->idx);
  
  	phy->dev.class = &wpan_phy_class;
37eb0edc8   Dmitry Eremin-Solenikov   wpan-phy: init ch...
162
163
  	phy->current_channel = -1; /* not initialised */
  	phy->current_page = 0; /* for compatibility */
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
164
  	return phy;
a6c0f8217   Denis Kirjanov   ieee802154: Fix p...
165
166
167
  
  out:
  	return NULL;
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
168
169
  }
  EXPORT_SYMBOL(wpan_phy_alloc);
e9cf356c0   Dmitry Eremin-Solenikov   wpan-phy: follow ...
170
  int wpan_phy_register(struct wpan_phy *phy)
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
171
  {
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	return device_add(&phy->dev);
  }
  EXPORT_SYMBOL(wpan_phy_register);
  
  void wpan_phy_unregister(struct wpan_phy *phy)
  {
  	device_del(&phy->dev);
  }
  EXPORT_SYMBOL(wpan_phy_unregister);
  
  void wpan_phy_free(struct wpan_phy *phy)
  {
  	put_device(&phy->dev);
  }
  EXPORT_SYMBOL(wpan_phy_free);
  
  static int __init wpan_phy_class_init(void)
  {
cb6b37635   Dmitry Eremin-Solenikov   ieee802154: merge...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
  	int rc;
  	rc = class_register(&wpan_phy_class);
  	if (rc)
  		goto err;
  
  	rc = ieee802154_nl_init();
  	if (rc)
  		goto err_nl;
  
  	return 0;
  err_nl:
  	class_unregister(&wpan_phy_class);
  err:
  	return rc;
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
204
  }
282a39546   Dmitry Eremin-Solenikov   ieee802154: make ...
205
  subsys_initcall(wpan_phy_class_init);
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
206
207
208
  
  static void __exit wpan_phy_class_exit(void)
  {
cb6b37635   Dmitry Eremin-Solenikov   ieee802154: merge...
209
  	ieee802154_nl_exit();
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
210
211
212
  	class_unregister(&wpan_phy_class);
  }
  module_exit(wpan_phy_class_exit);
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
213
  MODULE_LICENSE("GPL v2");
cb6b37635   Dmitry Eremin-Solenikov   ieee802154: merge...
214
215
  MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface");
  MODULE_AUTHOR("Dmitry Eremin-Solenikov");
2bfb1070b   Dmitry Eremin-Solenikov   ieee802154: add a...
216