blob: c26227adf8973a2ca7dba064993419388b3c3d6e [file] [log] [blame]
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001#include <linux/module.h>
2#include <linux/dcache.h>
3#include <linux/debugfs.h>
4#include <linux/delay.h>
5#include <linux/mm.h>
6#include <net/iw_handler.h>
Holger Schurig46868202007-05-25 00:37:28 -04007
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02008#include "dev.h"
9#include "decl.h"
10#include "host.h"
Dan Williams5bdb3ef2007-05-10 23:08:05 -040011#include "debugfs.h"
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020012
13static struct dentry *libertas_dir = NULL;
14static char *szStates[] = {
15 "Connected",
16 "Disconnected"
17};
18
Holger Schurig46868202007-05-25 00:37:28 -040019#ifdef PROC_DEBUG
20static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
21#endif
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020022
23static int open_file_generic(struct inode *inode, struct file *file)
24{
25 file->private_data = inode->i_private;
26 return 0;
27}
28
29static ssize_t write_file_dummy(struct file *file, const char __user *buf,
30 size_t count, loff_t *ppos)
31{
32 return -EINVAL;
33}
34
35static const size_t len = PAGE_SIZE;
36
37static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
38 size_t count, loff_t *ppos)
39{
40 wlan_private *priv = file->private_data;
41 size_t pos = 0;
42 unsigned long addr = get_zeroed_page(GFP_KERNEL);
43 char *buf = (char *)addr;
44 ssize_t res;
45
46 pos += snprintf(buf+pos, len-pos, "state = %s\n",
47 szStates[priv->adapter->connect_status]);
48 pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
49 (u32) priv->adapter->regioncode);
50
51 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
52
53 free_page(addr);
54 return res;
55}
56
57
58static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
59 size_t count, loff_t *ppos)
60{
61 wlan_private *priv = file->private_data;
62 size_t pos = 0;
63 int numscansdone = 0, res;
64 unsigned long addr = get_zeroed_page(GFP_KERNEL);
65 char *buf = (char *)addr;
Dan Williamsfcdb53d2007-05-25 16:15:56 -040066 struct bss_descriptor * iter_bss;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020067
68 pos += snprintf(buf+pos, len-pos,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020069 "# | ch | ss | bssid | cap | TSF | Qual | SSID \n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020070
Dan Williamsfcdb53d2007-05-25 16:15:56 -040071 mutex_lock(&priv->adapter->lock);
72 list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020073 u16 cap;
74
Dan Williamsfcdb53d2007-05-25 16:15:56 -040075 memcpy(&cap, &iter_bss->cap, sizeof(cap));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020076 pos += snprintf(buf+pos, len-pos,
77 "%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
Dan Williamsfcdb53d2007-05-25 16:15:56 -040078 numscansdone, iter_bss->channel, iter_bss->rssi,
79 iter_bss->bssid[0], iter_bss->bssid[1],
80 iter_bss->bssid[2], iter_bss->bssid[3],
81 iter_bss->bssid[4], iter_bss->bssid[5]);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020082 pos += snprintf(buf+pos, len-pos, " %04x-", cap);
83 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
Dan Williamsfcdb53d2007-05-25 16:15:56 -040084 iter_bss->cap.ibss ? 'A' : 'I',
85 iter_bss->cap.privacy ? 'P' : ' ',
86 iter_bss->cap.spectrummgmt ? 'S' : ' ');
87 pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf);
88 pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi));
89 pos += snprintf(buf+pos, len-pos, " %s\n", iter_bss->ssid.ssid);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020090
91 numscansdone++;
92 }
Dan Williamsfcdb53d2007-05-25 16:15:56 -040093 mutex_unlock(&priv->adapter->lock);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -020094
95 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
96
97 free_page(addr);
98 return res;
99}
100
101static ssize_t libertas_sleepparams_write(struct file *file,
102 const char __user *user_buf, size_t count,
103 loff_t *ppos)
104{
105 wlan_private *priv = file->private_data;
106 ssize_t buf_size, res;
107 int p1, p2, p3, p4, p5, p6;
108 struct sleep_params sp;
109 unsigned long addr = get_zeroed_page(GFP_KERNEL);
110 char *buf = (char *)addr;
111
112 buf_size = min(count, len - 1);
113 if (copy_from_user(buf, user_buf, buf_size)) {
114 res = -EFAULT;
115 goto out_unlock;
116 }
117 res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
118 if (res != 6) {
119 res = -EFAULT;
120 goto out_unlock;
121 }
122 sp.sp_error = p1;
123 sp.sp_offset = p2;
124 sp.sp_stabletime = p3;
125 sp.sp_calcontrol = p4;
126 sp.sp_extsleepclk = p5;
127 sp.sp_reserved = p6;
128
129 memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params));
130
131 res = libertas_prepare_and_send_command(priv,
132 cmd_802_11_sleep_params,
133 cmd_act_set,
134 cmd_option_waitforrsp, 0, NULL);
135
136 if (!res)
137 res = count;
138 else
139 res = -EINVAL;
140
141out_unlock:
142 free_page(addr);
143 return res;
144}
145
146static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf,
147 size_t count, loff_t *ppos)
148{
149 wlan_private *priv = file->private_data;
150 wlan_adapter *adapter = priv->adapter;
151 ssize_t res;
152 size_t pos = 0;
153 unsigned long addr = get_zeroed_page(GFP_KERNEL);
154 char *buf = (char *)addr;
155
156 res = libertas_prepare_and_send_command(priv,
157 cmd_802_11_sleep_params,
158 cmd_act_get,
159 cmd_option_waitforrsp, 0, NULL);
160 if (res) {
161 res = -EFAULT;
162 goto out_unlock;
163 }
164
165 pos += snprintf(buf, len, "%d %d %d %d %d %d\n", adapter->sp.sp_error,
166 adapter->sp.sp_offset, adapter->sp.sp_stabletime,
167 adapter->sp.sp_calcontrol, adapter->sp.sp_extsleepclk,
168 adapter->sp.sp_reserved);
169
170 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
171
172out_unlock:
173 free_page(addr);
174 return res;
175}
176
177static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
178 size_t count, loff_t *ppos)
179{
180 wlan_private *priv = file->private_data;
181 ssize_t res, buf_size;
182 struct WLAN_802_11_SSID extscan_ssid;
183 union iwreq_data wrqu;
184 unsigned long addr = get_zeroed_page(GFP_KERNEL);
185 char *buf = (char *)addr;
186
187 buf_size = min(count, len - 1);
188 if (copy_from_user(buf, userbuf, buf_size)) {
189 res = -EFAULT;
190 goto out_unlock;
191 }
192
193 memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
194 extscan_ssid.ssidlength = strlen(buf)-1;
195
196 libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1);
197
198 memset(&wrqu, 0, sizeof(union iwreq_data));
Holger Schurig634b8f42007-05-25 13:05:16 -0400199 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200200
201out_unlock:
202 free_page(addr);
203 return count;
204}
205
206static int libertas_parse_chan(char *buf, size_t count,
207 struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur)
208{
209 char *start, *end, *hold, *str;
210 int i = 0;
211
212 start = strstr(buf, "chan=");
213 if (!start)
214 return -EINVAL;
215 start += 5;
216 end = strstr(start, " ");
217 if (!end)
218 end = buf + count;
219 hold = kzalloc((end - start)+1, GFP_KERNEL);
220 if (!hold)
221 return -ENOMEM;
222 strncpy(hold, start, end - start);
223 hold[(end-start)+1] = '\0';
224 while(hold && (str = strsep(&hold, ","))) {
225 int chan;
226 char band, passive = 0;
227 sscanf(str, "%d%c%c", &chan, &band, &passive);
228 scan_cfg->chanlist[i].channumber = chan;
229 scan_cfg->chanlist[i].scantype = passive ? 1 : 0;
230 if (band == 'b' || band == 'g')
231 scan_cfg->chanlist[i].radiotype = 0;
232 else if (band == 'a')
233 scan_cfg->chanlist[i].radiotype = 1;
234
235 scan_cfg->chanlist[i].scantime = dur;
236 i++;
237 }
238
239 kfree(hold);
240 return i;
241}
242
243static void libertas_parse_bssid(char *buf, size_t count,
244 struct wlan_ioctl_user_scan_cfg *scan_cfg)
245{
246 char *hold;
247 unsigned int mac[ETH_ALEN];
248 int i;
249
250 hold = strstr(buf, "bssid=");
251 if (!hold)
252 return;
253 hold += 6;
254 sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3,
255 mac+4, mac+5);
256 for(i=0;i<ETH_ALEN;i++)
257 scan_cfg->specificBSSID[i] = mac[i];
258}
259
260static void libertas_parse_ssid(char *buf, size_t count,
261 struct wlan_ioctl_user_scan_cfg *scan_cfg)
262{
263 char *hold, *end;
264 ssize_t size;
265
266 hold = strstr(buf, "ssid=");
267 if (!hold)
268 return;
269 hold += 5;
270 end = strstr(hold, " ");
271 if (!end)
272 end = buf + count - 1;
273
Dan Williams4269e2a2007-05-10 23:10:18 -0400274 size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200275 strncpy(scan_cfg->specificSSID, hold, size);
276
277 return;
278}
279
280static void libertas_parse_keep(char *buf, size_t count,
281 struct wlan_ioctl_user_scan_cfg *scan_cfg)
282{
283 char *hold;
284 int val;
285
286 hold = strstr(buf, "keep=");
287 if (!hold)
288 return;
289 hold += 5;
290 sscanf(hold, "%d", &val);
291
292 if (val != 0)
293 val = 1;
294
295 scan_cfg->keeppreviousscan = val;
296 return;
297}
298
299static int libertas_parse_dur(char *buf, size_t count,
300 struct wlan_ioctl_user_scan_cfg *scan_cfg)
301{
302 char *hold;
303 int val;
304
305 hold = strstr(buf, "dur=");
306 if (!hold)
307 return 0;
308 hold += 4;
309 sscanf(hold, "%d", &val);
310
311 return val;
312}
313
314static void libertas_parse_probes(char *buf, size_t count,
315 struct wlan_ioctl_user_scan_cfg *scan_cfg)
316{
317 char *hold;
318 int val;
319
320 hold = strstr(buf, "probes=");
321 if (!hold)
322 return;
323 hold += 7;
324 sscanf(hold, "%d", &val);
325
326 scan_cfg->numprobes = val;
327
328 return;
329}
330
331static void libertas_parse_type(char *buf, size_t count,
332 struct wlan_ioctl_user_scan_cfg *scan_cfg)
333{
334 char *hold;
335 int val;
336
337 hold = strstr(buf, "type=");
338 if (!hold)
339 return;
340 hold += 5;
341 sscanf(hold, "%d", &val);
342
343 /* type=1,2 or 3 */
344 if (val < 1 || val > 3)
345 return;
346
347 scan_cfg->bsstype = val;
348
349 return;
350}
351
352static ssize_t libertas_setuserscan(struct file *file,
353 const char __user *userbuf,
354 size_t count, loff_t *ppos)
355{
356 wlan_private *priv = file->private_data;
357 ssize_t res, buf_size;
358 struct wlan_ioctl_user_scan_cfg *scan_cfg;
359 union iwreq_data wrqu;
360 int dur;
361 unsigned long addr = get_zeroed_page(GFP_KERNEL);
362 char *buf = (char *)addr;
363
364 scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL);
365 if (!scan_cfg)
366 return -ENOMEM;
367
368 buf_size = min(count, len - 1);
369 if (copy_from_user(buf, userbuf, buf_size)) {
370 res = -EFAULT;
371 goto out_unlock;
372 }
373
374 scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY;
375
376 dur = libertas_parse_dur(buf, count, scan_cfg);
377 libertas_parse_chan(buf, count, scan_cfg, dur);
378 libertas_parse_bssid(buf, count, scan_cfg);
379 libertas_parse_ssid(buf, count, scan_cfg);
380 libertas_parse_keep(buf, count, scan_cfg);
381 libertas_parse_probes(buf, count, scan_cfg);
382 libertas_parse_type(buf, count, scan_cfg);
383
Marcelo Tosatti2be92192007-05-25 00:33:28 -0400384 wlan_scan_networks(priv, scan_cfg, 1);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200385 wait_event_interruptible(priv->adapter->cmd_pending,
386 !priv->adapter->nr_cmd_pending);
387
388 memset(&wrqu, 0x00, sizeof(union iwreq_data));
Holger Schurig634b8f42007-05-25 13:05:16 -0400389 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200390
391out_unlock:
392 free_page(addr);
393 kfree(scan_cfg);
394 return count;
395}
396
397static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
398 struct cmd_ctrl_node **cmdnode,
399 struct cmd_ds_command **cmd)
400{
401 u16 wait_option = cmd_option_waitforrsp;
402
403 if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
Holger Schurig9012b282007-05-25 11:27:16 -0400404 lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200405 return -ENOMEM;
406 }
407 if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
Holger Schurig9012b282007-05-25 11:27:16 -0400408 lbs_deb_debugfs("failed to allocate response buffer!\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -0200409 return -ENOMEM;
410 }
411 libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
412 init_waitqueue_head(&(*cmdnode)->cmdwait_q);
413 (*cmdnode)->pdata_buf = *response_buf;
414 (*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
415 (*cmdnode)->cmdwaitqwoken = 0;
416 *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
417 (*cmd)->command = cmd_802_11_subscribe_event;
418 (*cmd)->seqnum = ++priv->adapter->seqnum;
419 (*cmd)->result = 0;
420 return 0;
421}
422
423static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
424 size_t count, loff_t *ppos)
425{
426 wlan_private *priv = file->private_data;
427 wlan_adapter *adapter = priv->adapter;
428 struct cmd_ctrl_node *pcmdnode;
429 struct cmd_ds_command *pcmdptr;
430 struct cmd_ds_802_11_subscribe_event *event;
431 void *response_buf;
432 int res, cmd_len;
433 ssize_t pos = 0;
434 unsigned long addr = get_zeroed_page(GFP_KERNEL);
435 char *buf = (char *)addr;
436
437 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
438 if (res < 0) {
439 free_page(addr);
440 return res;
441 }
442
443 event = &pcmdptr->params.subscribe_event;
444 event->action = cmd_act_get;
445 pcmdptr->size =
446 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
447 libertas_queue_cmd(adapter, pcmdnode, 1);
448 wake_up_interruptible(&priv->mainthread.waitq);
449
450 /* Sleep until response is generated by FW */
451 wait_event_interruptible(pcmdnode->cmdwait_q,
452 pcmdnode->cmdwaitqwoken);
453
454 pcmdptr = response_buf;
455 if (pcmdptr->result) {
456 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
457 pcmdptr->result);
458 kfree(response_buf);
459 free_page(addr);
460 return 0;
461 }
462
463 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
464 lbs_pr_err("command response incorrect!\n");
465 kfree(response_buf);
466 free_page(addr);
467 return 0;
468 }
469
470 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
471 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
472 while (cmd_len < pcmdptr->size) {
473 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
474 switch(header->type) {
475 struct mrvlietypes_rssithreshold *Lowrssi;
476 case TLV_TYPE_RSSI_LOW:
477 Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
478 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
479 Lowrssi->rssivalue,
480 Lowrssi->rssifreq,
481 (event->events & 0x0001)?1:0);
482 default:
483 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
484 break;
485 }
486 }
487
488 kfree(response_buf);
489 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
490 free_page(addr);
491 return res;
492}
493
494static u16 libertas_get_events_bitmap(wlan_private *priv)
495{
496 wlan_adapter *adapter = priv->adapter;
497 struct cmd_ctrl_node *pcmdnode;
498 struct cmd_ds_command *pcmdptr;
499 struct cmd_ds_802_11_subscribe_event *event;
500 void *response_buf;
501 int res;
502 u16 event_bitmap;
503
504 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
505 if (res < 0)
506 return res;
507
508 event = &pcmdptr->params.subscribe_event;
509 event->action = cmd_act_get;
510 pcmdptr->size =
511 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
512 libertas_queue_cmd(adapter, pcmdnode, 1);
513 wake_up_interruptible(&priv->mainthread.waitq);
514
515 /* Sleep until response is generated by FW */
516 wait_event_interruptible(pcmdnode->cmdwait_q,
517 pcmdnode->cmdwaitqwoken);
518
519 pcmdptr = response_buf;
520
521 if (pcmdptr->result) {
522 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
523 pcmdptr->result);
524 kfree(response_buf);
525 return 0;
526 }
527
528 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
529 lbs_pr_err("command response incorrect!\n");
530 kfree(response_buf);
531 return 0;
532 }
533
534 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
535 event_bitmap = event->events;
536 kfree(response_buf);
537 return event_bitmap;
538}
539
540static ssize_t libertas_lowrssi_write(struct file *file,
541 const char __user *userbuf,
542 size_t count, loff_t *ppos)
543{
544 wlan_private *priv = file->private_data;
545 wlan_adapter *adapter = priv->adapter;
546 ssize_t res, buf_size;
547 int value, freq, subscribed, cmd_len;
548 struct cmd_ctrl_node *pcmdnode;
549 struct cmd_ds_command *pcmdptr;
550 struct cmd_ds_802_11_subscribe_event *event;
551 struct mrvlietypes_rssithreshold *rssi_threshold;
552 void *response_buf;
553 u16 event_bitmap;
554 u8 *ptr;
555 unsigned long addr = get_zeroed_page(GFP_KERNEL);
556 char *buf = (char *)addr;
557
558 buf_size = min(count, len - 1);
559 if (copy_from_user(buf, userbuf, buf_size)) {
560 res = -EFAULT;
561 goto out_unlock;
562 }
563 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
564 if (res != 3) {
565 res = -EFAULT;
566 goto out_unlock;
567 }
568
569 event_bitmap = libertas_get_events_bitmap(priv);
570
571 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
572 if (res < 0)
573 goto out_unlock;
574
575 event = &pcmdptr->params.subscribe_event;
576 event->action = cmd_act_set;
577 pcmdptr->size = cpu_to_le16(S_DS_GEN +
578 sizeof(struct cmd_ds_802_11_subscribe_event) +
579 sizeof(struct mrvlietypes_rssithreshold));
580
581 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
582 ptr = (u8*) pcmdptr+cmd_len;
583 rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
584 rssi_threshold->header.type = cpu_to_le16(0x0104);
585 rssi_threshold->header.len = 2;
586 rssi_threshold->rssivalue = cpu_to_le16(value);
587 rssi_threshold->rssifreq = cpu_to_le16(freq);
588 event_bitmap |= subscribed ? 0x0001 : 0x0;
589 event->events = event_bitmap;
590
591 libertas_queue_cmd(adapter, pcmdnode, 1);
592 wake_up_interruptible(&priv->mainthread.waitq);
593
594 /* Sleep until response is generated by FW */
595 wait_event_interruptible(pcmdnode->cmdwait_q,
596 pcmdnode->cmdwaitqwoken);
597
598 pcmdptr = response_buf;
599
600 if (pcmdptr->result) {
601 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
602 pcmdptr->result);
603 kfree(response_buf);
604 free_page(addr);
605 return 0;
606 }
607
608 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
609 lbs_pr_err("command response incorrect!\n");
610 kfree(response_buf);
611 free_page(addr);
612 return 0;
613 }
614
615 res = count;
616out_unlock:
617 free_page(addr);
618 return res;
619}
620
621static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
622 size_t count, loff_t *ppos)
623{
624 wlan_private *priv = file->private_data;
625 wlan_adapter *adapter = priv->adapter;
626 struct cmd_ctrl_node *pcmdnode;
627 struct cmd_ds_command *pcmdptr;
628 struct cmd_ds_802_11_subscribe_event *event;
629 void *response_buf;
630 int res, cmd_len;
631 ssize_t pos = 0;
632 unsigned long addr = get_zeroed_page(GFP_KERNEL);
633 char *buf = (char *)addr;
634
635 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
636 if (res < 0) {
637 free_page(addr);
638 return res;
639 }
640
641 event = &pcmdptr->params.subscribe_event;
642 event->action = cmd_act_get;
643 pcmdptr->size =
644 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
645 libertas_queue_cmd(adapter, pcmdnode, 1);
646 wake_up_interruptible(&priv->mainthread.waitq);
647
648 /* Sleep until response is generated by FW */
649 wait_event_interruptible(pcmdnode->cmdwait_q,
650 pcmdnode->cmdwaitqwoken);
651
652 pcmdptr = response_buf;
653
654 if (pcmdptr->result) {
655 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
656 pcmdptr->result);
657 kfree(response_buf);
658 free_page(addr);
659 return 0;
660 }
661
662 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
663 lbs_pr_err("command response incorrect!\n");
664 kfree(response_buf);
665 free_page(addr);
666 return 0;
667 }
668
669 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
670 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
671 while (cmd_len < pcmdptr->size) {
672 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
673 switch(header->type) {
674 struct mrvlietypes_snrthreshold *LowSnr;
675 case TLV_TYPE_SNR_LOW:
676 LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
677 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
678 LowSnr->snrvalue,
679 LowSnr->snrfreq,
680 (event->events & 0x0002)?1:0);
681 default:
682 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
683 break;
684 }
685 }
686
687 kfree(response_buf);
688
689 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
690 free_page(addr);
691 return res;
692}
693
694static ssize_t libertas_lowsnr_write(struct file *file,
695 const char __user *userbuf,
696 size_t count, loff_t *ppos)
697{
698 wlan_private *priv = file->private_data;
699 wlan_adapter *adapter = priv->adapter;
700 ssize_t res, buf_size;
701 int value, freq, subscribed, cmd_len;
702 struct cmd_ctrl_node *pcmdnode;
703 struct cmd_ds_command *pcmdptr;
704 struct cmd_ds_802_11_subscribe_event *event;
705 struct mrvlietypes_snrthreshold *snr_threshold;
706 void *response_buf;
707 u16 event_bitmap;
708 u8 *ptr;
709 unsigned long addr = get_zeroed_page(GFP_KERNEL);
710 char *buf = (char *)addr;
711
712 buf_size = min(count, len - 1);
713 if (copy_from_user(buf, userbuf, buf_size)) {
714 res = -EFAULT;
715 goto out_unlock;
716 }
717 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
718 if (res != 3) {
719 res = -EFAULT;
720 goto out_unlock;
721 }
722
723 event_bitmap = libertas_get_events_bitmap(priv);
724
725 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
726 if (res < 0)
727 goto out_unlock;
728
729 event = &pcmdptr->params.subscribe_event;
730 event->action = cmd_act_set;
731 pcmdptr->size = cpu_to_le16(S_DS_GEN +
732 sizeof(struct cmd_ds_802_11_subscribe_event) +
733 sizeof(struct mrvlietypes_snrthreshold));
734 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
735 ptr = (u8*) pcmdptr+cmd_len;
736 snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
737 snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
738 snr_threshold->header.len = 2;
739 snr_threshold->snrvalue = cpu_to_le16(value);
740 snr_threshold->snrfreq = cpu_to_le16(freq);
741 event_bitmap |= subscribed ? 0x0002 : 0x0;
742 event->events = event_bitmap;
743
744 libertas_queue_cmd(adapter, pcmdnode, 1);
745 wake_up_interruptible(&priv->mainthread.waitq);
746
747 /* Sleep until response is generated by FW */
748 wait_event_interruptible(pcmdnode->cmdwait_q,
749 pcmdnode->cmdwaitqwoken);
750
751 pcmdptr = response_buf;
752
753 if (pcmdptr->result) {
754 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
755 pcmdptr->result);
756 kfree(response_buf);
757 free_page(addr);
758 return 0;
759 }
760
761 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
762 lbs_pr_err("command response incorrect!\n");
763 kfree(response_buf);
764 free_page(addr);
765 return 0;
766 }
767
768 res = count;
769
770out_unlock:
771 free_page(addr);
772 return res;
773}
774
775static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
776 size_t count, loff_t *ppos)
777{
778 wlan_private *priv = file->private_data;
779 wlan_adapter *adapter = priv->adapter;
780 struct cmd_ctrl_node *pcmdnode;
781 struct cmd_ds_command *pcmdptr;
782 struct cmd_ds_802_11_subscribe_event *event;
783 void *response_buf;
784 int res, cmd_len;
785 ssize_t pos = 0;
786 unsigned long addr = get_zeroed_page(GFP_KERNEL);
787 char *buf = (char *)addr;
788
789 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
790 if (res < 0) {
791 free_page(addr);
792 return res;
793 }
794
795 event = &pcmdptr->params.subscribe_event;
796 event->action = cmd_act_get;
797 pcmdptr->size =
798 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
799 libertas_queue_cmd(adapter, pcmdnode, 1);
800 wake_up_interruptible(&priv->mainthread.waitq);
801
802 /* Sleep until response is generated by FW */
803 wait_event_interruptible(pcmdnode->cmdwait_q,
804 pcmdnode->cmdwaitqwoken);
805
806 pcmdptr = response_buf;
807
808 if (pcmdptr->result) {
809 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
810 pcmdptr->result);
811 kfree(response_buf);
812 free_page(addr);
813 return 0;
814 }
815
816 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
817 lbs_pr_err("command response incorrect!\n");
818 kfree(response_buf);
819 free_page(addr);
820 return 0;
821 }
822
823 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
824 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
825 while (cmd_len < pcmdptr->size) {
826 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
827 switch(header->type) {
828 struct mrvlietypes_failurecount *failcount;
829 case TLV_TYPE_FAILCOUNT:
830 failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len);
831 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
832 failcount->failvalue,
833 failcount->Failfreq,
834 (event->events & 0x0004)?1:0);
835 default:
836 cmd_len += sizeof(struct mrvlietypes_failurecount);
837 break;
838 }
839 }
840
841 kfree(response_buf);
842 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
843 free_page(addr);
844 return res;
845}
846
847static ssize_t libertas_failcount_write(struct file *file,
848 const char __user *userbuf,
849 size_t count, loff_t *ppos)
850{
851 wlan_private *priv = file->private_data;
852 wlan_adapter *adapter = priv->adapter;
853 ssize_t res, buf_size;
854 int value, freq, subscribed, cmd_len;
855 struct cmd_ctrl_node *pcmdnode;
856 struct cmd_ds_command *pcmdptr;
857 struct cmd_ds_802_11_subscribe_event *event;
858 struct mrvlietypes_failurecount *failcount;
859 void *response_buf;
860 u16 event_bitmap;
861 u8 *ptr;
862 unsigned long addr = get_zeroed_page(GFP_KERNEL);
863 char *buf = (char *)addr;
864
865 buf_size = min(count, len - 1);
866 if (copy_from_user(buf, userbuf, buf_size)) {
867 res = -EFAULT;
868 goto out_unlock;
869 }
870 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
871 if (res != 3) {
872 res = -EFAULT;
873 goto out_unlock;
874 }
875
876 event_bitmap = libertas_get_events_bitmap(priv);
877
878 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
879 if (res < 0)
880 goto out_unlock;
881
882 event = &pcmdptr->params.subscribe_event;
883 event->action = cmd_act_set;
884 pcmdptr->size = cpu_to_le16(S_DS_GEN +
885 sizeof(struct cmd_ds_802_11_subscribe_event) +
886 sizeof(struct mrvlietypes_failurecount));
887 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
888 ptr = (u8*) pcmdptr+cmd_len;
889 failcount = (struct mrvlietypes_failurecount *)(ptr);
890 failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
891 failcount->header.len = 2;
892 failcount->failvalue = cpu_to_le16(value);
893 failcount->Failfreq = cpu_to_le16(freq);
894 event_bitmap |= subscribed ? 0x0004 : 0x0;
895 event->events = event_bitmap;
896
897 libertas_queue_cmd(adapter, pcmdnode, 1);
898 wake_up_interruptible(&priv->mainthread.waitq);
899
900 /* Sleep until response is generated by FW */
901 wait_event_interruptible(pcmdnode->cmdwait_q,
902 pcmdnode->cmdwaitqwoken);
903
904 pcmdptr = (struct cmd_ds_command *)response_buf;
905
906 if (pcmdptr->result) {
907 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
908 pcmdptr->result);
909 kfree(response_buf);
910 free_page(addr);
911 return 0;
912 }
913
914 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
915 lbs_pr_err("command response incorrect!\n");
916 kfree(response_buf);
917 free_page(addr);
918 return 0;
919 }
920
921 res = count;
922out_unlock:
923 free_page(addr);
924 return res;
925}
926
927static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
928 size_t count, loff_t *ppos)
929{
930 wlan_private *priv = file->private_data;
931 wlan_adapter *adapter = priv->adapter;
932 struct cmd_ctrl_node *pcmdnode;
933 struct cmd_ds_command *pcmdptr;
934 struct cmd_ds_802_11_subscribe_event *event;
935 void *response_buf;
936 int res, cmd_len;
937 ssize_t pos = 0;
938 unsigned long addr = get_zeroed_page(GFP_KERNEL);
939 char *buf = (char *)addr;
940
941 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
942 if (res < 0) {
943 free_page(addr);
944 return res;
945 }
946
947 event = &pcmdptr->params.subscribe_event;
948 event->action = cmd_act_get;
949 pcmdptr->size =
950 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
951 libertas_queue_cmd(adapter, pcmdnode, 1);
952 wake_up_interruptible(&priv->mainthread.waitq);
953
954 /* Sleep until response is generated by FW */
955 wait_event_interruptible(pcmdnode->cmdwait_q,
956 pcmdnode->cmdwaitqwoken);
957
958 pcmdptr = response_buf;
959
960 if (pcmdptr->result) {
961 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
962 pcmdptr->result);
963 free_page(addr);
964 kfree(response_buf);
965 return 0;
966 }
967
968 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
969 lbs_pr_err("command response incorrect!\n");
970 free_page(addr);
971 kfree(response_buf);
972 return 0;
973 }
974
975 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
976 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
977 while (cmd_len < pcmdptr->size) {
978 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
979 switch(header->type) {
980 struct mrvlietypes_beaconsmissed *bcnmiss;
981 case TLV_TYPE_BCNMISS:
982 bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len);
983 pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
984 bcnmiss->beaconmissed,
985 (event->events & 0x0008)?1:0);
986 default:
987 cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
988 break;
989 }
990 }
991
992 kfree(response_buf);
993
994 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
995 free_page(addr);
996 return res;
997}
998
999static ssize_t libertas_bcnmiss_write(struct file *file,
1000 const char __user *userbuf,
1001 size_t count, loff_t *ppos)
1002{
1003 wlan_private *priv = file->private_data;
1004 wlan_adapter *adapter = priv->adapter;
1005 ssize_t res, buf_size;
1006 int value, freq, subscribed, cmd_len;
1007 struct cmd_ctrl_node *pcmdnode;
1008 struct cmd_ds_command *pcmdptr;
1009 struct cmd_ds_802_11_subscribe_event *event;
1010 struct mrvlietypes_beaconsmissed *bcnmiss;
1011 void *response_buf;
1012 u16 event_bitmap;
1013 u8 *ptr;
1014 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1015 char *buf = (char *)addr;
1016
1017 buf_size = min(count, len - 1);
1018 if (copy_from_user(buf, userbuf, buf_size)) {
1019 res = -EFAULT;
1020 goto out_unlock;
1021 }
1022 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1023 if (res != 3) {
1024 res = -EFAULT;
1025 goto out_unlock;
1026 }
1027
1028 event_bitmap = libertas_get_events_bitmap(priv);
1029
1030 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1031 if (res < 0)
1032 goto out_unlock;
1033
1034 event = &pcmdptr->params.subscribe_event;
1035 event->action = cmd_act_set;
1036 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1037 sizeof(struct cmd_ds_802_11_subscribe_event) +
1038 sizeof(struct mrvlietypes_beaconsmissed));
1039 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1040 ptr = (u8*) pcmdptr+cmd_len;
1041 bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
1042 bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
1043 bcnmiss->header.len = 2;
1044 bcnmiss->beaconmissed = cpu_to_le16(value);
1045 event_bitmap |= subscribed ? 0x0008 : 0x0;
1046 event->events = event_bitmap;
1047
1048 libertas_queue_cmd(adapter, pcmdnode, 1);
1049 wake_up_interruptible(&priv->mainthread.waitq);
1050
1051 /* Sleep until response is generated by FW */
1052 wait_event_interruptible(pcmdnode->cmdwait_q,
1053 pcmdnode->cmdwaitqwoken);
1054
1055 pcmdptr = response_buf;
1056
1057 if (pcmdptr->result) {
1058 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1059 pcmdptr->result);
1060 kfree(response_buf);
1061 free_page(addr);
1062 return 0;
1063 }
1064
1065 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1066 lbs_pr_err("command response incorrect!\n");
1067 free_page(addr);
1068 kfree(response_buf);
1069 return 0;
1070 }
1071
1072 res = count;
1073out_unlock:
1074 free_page(addr);
1075 return res;
1076}
1077
1078static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
1079 size_t count, loff_t *ppos)
1080{
1081 wlan_private *priv = file->private_data;
1082 wlan_adapter *adapter = priv->adapter;
1083 struct cmd_ctrl_node *pcmdnode;
1084 struct cmd_ds_command *pcmdptr;
1085 struct cmd_ds_802_11_subscribe_event *event;
1086 void *response_buf;
1087 int res, cmd_len;
1088 ssize_t pos = 0;
1089 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1090 char *buf = (char *)addr;
1091
1092 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1093 if (res < 0) {
1094 free_page(addr);
1095 return res;
1096 }
1097
1098 event = &pcmdptr->params.subscribe_event;
1099 event->action = cmd_act_get;
1100 pcmdptr->size =
1101 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
1102 libertas_queue_cmd(adapter, pcmdnode, 1);
1103 wake_up_interruptible(&priv->mainthread.waitq);
1104
1105 /* Sleep until response is generated by FW */
1106 wait_event_interruptible(pcmdnode->cmdwait_q,
1107 pcmdnode->cmdwaitqwoken);
1108
1109 pcmdptr = response_buf;
1110
1111 if (pcmdptr->result) {
1112 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1113 pcmdptr->result);
1114 kfree(response_buf);
1115 free_page(addr);
1116 return 0;
1117 }
1118
1119 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1120 lbs_pr_err("command response incorrect!\n");
1121 kfree(response_buf);
1122 free_page(addr);
1123 return 0;
1124 }
1125
1126 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1127 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
1128 while (cmd_len < pcmdptr->size) {
1129 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
1130 switch(header->type) {
1131 struct mrvlietypes_rssithreshold *Highrssi;
1132 case TLV_TYPE_RSSI_HIGH:
1133 Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
1134 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1135 Highrssi->rssivalue,
1136 Highrssi->rssifreq,
1137 (event->events & 0x0010)?1:0);
1138 default:
1139 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1140 break;
1141 }
1142 }
1143
1144 kfree(response_buf);
1145
1146 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1147 free_page(addr);
1148 return res;
1149}
1150
1151static ssize_t libertas_highrssi_write(struct file *file,
1152 const char __user *userbuf,
1153 size_t count, loff_t *ppos)
1154{
1155 wlan_private *priv = file->private_data;
1156 wlan_adapter *adapter = priv->adapter;
1157 ssize_t res, buf_size;
1158 int value, freq, subscribed, cmd_len;
1159 struct cmd_ctrl_node *pcmdnode;
1160 struct cmd_ds_command *pcmdptr;
1161 struct cmd_ds_802_11_subscribe_event *event;
1162 struct mrvlietypes_rssithreshold *rssi_threshold;
1163 void *response_buf;
1164 u16 event_bitmap;
1165 u8 *ptr;
1166 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1167 char *buf = (char *)addr;
1168
1169 buf_size = min(count, len - 1);
1170 if (copy_from_user(buf, userbuf, buf_size)) {
1171 res = -EFAULT;
1172 goto out_unlock;
1173 }
1174 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1175 if (res != 3) {
1176 res = -EFAULT;
1177 goto out_unlock;
1178 }
1179
1180 event_bitmap = libertas_get_events_bitmap(priv);
1181
1182 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1183 if (res < 0)
1184 goto out_unlock;
1185
1186 event = &pcmdptr->params.subscribe_event;
1187 event->action = cmd_act_set;
1188 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1189 sizeof(struct cmd_ds_802_11_subscribe_event) +
1190 sizeof(struct mrvlietypes_rssithreshold));
1191 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1192 ptr = (u8*) pcmdptr+cmd_len;
1193 rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
1194 rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
1195 rssi_threshold->header.len = 2;
1196 rssi_threshold->rssivalue = cpu_to_le16(value);
1197 rssi_threshold->rssifreq = cpu_to_le16(freq);
1198 event_bitmap |= subscribed ? 0x0010 : 0x0;
1199 event->events = event_bitmap;
1200
1201 libertas_queue_cmd(adapter, pcmdnode, 1);
1202 wake_up_interruptible(&priv->mainthread.waitq);
1203
1204 /* Sleep until response is generated by FW */
1205 wait_event_interruptible(pcmdnode->cmdwait_q,
1206 pcmdnode->cmdwaitqwoken);
1207
1208 pcmdptr = response_buf;
1209
1210 if (pcmdptr->result) {
1211 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1212 pcmdptr->result);
1213 kfree(response_buf);
1214 return 0;
1215 }
1216
1217 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1218 lbs_pr_err("command response incorrect!\n");
1219 kfree(response_buf);
1220 return 0;
1221 }
1222
1223 res = count;
1224out_unlock:
1225 free_page(addr);
1226 return res;
1227}
1228
1229static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
1230 size_t count, loff_t *ppos)
1231{
1232 wlan_private *priv = file->private_data;
1233 wlan_adapter *adapter = priv->adapter;
1234 struct cmd_ctrl_node *pcmdnode;
1235 struct cmd_ds_command *pcmdptr;
1236 struct cmd_ds_802_11_subscribe_event *event;
1237 void *response_buf;
1238 int res, cmd_len;
1239 ssize_t pos = 0;
1240 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1241 char *buf = (char *)addr;
1242
1243 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1244 if (res < 0) {
1245 free_page(addr);
1246 return res;
1247 }
1248
1249 event = &pcmdptr->params.subscribe_event;
1250 event->action = cmd_act_get;
1251 pcmdptr->size =
1252 cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
1253 libertas_queue_cmd(adapter, pcmdnode, 1);
1254 wake_up_interruptible(&priv->mainthread.waitq);
1255
1256 /* Sleep until response is generated by FW */
1257 wait_event_interruptible(pcmdnode->cmdwait_q,
1258 pcmdnode->cmdwaitqwoken);
1259
1260 pcmdptr = response_buf;
1261
1262 if (pcmdptr->result) {
1263 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1264 pcmdptr->result);
1265 kfree(response_buf);
1266 free_page(addr);
1267 return 0;
1268 }
1269
1270 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1271 lbs_pr_err("command response incorrect!\n");
1272 kfree(response_buf);
1273 free_page(addr);
1274 return 0;
1275 }
1276
1277 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1278 event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
1279 while (cmd_len < pcmdptr->size) {
1280 struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
1281 switch(header->type) {
1282 struct mrvlietypes_snrthreshold *HighSnr;
1283 case TLV_TYPE_SNR_HIGH:
1284 HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
1285 pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
1286 HighSnr->snrvalue,
1287 HighSnr->snrfreq,
1288 (event->events & 0x0020)?1:0);
1289 default:
1290 cmd_len += sizeof(struct mrvlietypes_snrthreshold);
1291 break;
1292 }
1293 }
1294
1295 kfree(response_buf);
1296
1297 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1298 free_page(addr);
1299 return res;
1300}
1301
1302static ssize_t libertas_highsnr_write(struct file *file,
1303 const char __user *userbuf,
1304 size_t count, loff_t *ppos)
1305{
1306 wlan_private *priv = file->private_data;
1307 wlan_adapter *adapter = priv->adapter;
1308 ssize_t res, buf_size;
1309 int value, freq, subscribed, cmd_len;
1310 struct cmd_ctrl_node *pcmdnode;
1311 struct cmd_ds_command *pcmdptr;
1312 struct cmd_ds_802_11_subscribe_event *event;
1313 struct mrvlietypes_snrthreshold *snr_threshold;
1314 void *response_buf;
1315 u16 event_bitmap;
1316 u8 *ptr;
1317 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1318 char *buf = (char *)addr;
1319
1320 buf_size = min(count, len - 1);
1321 if (copy_from_user(buf, userbuf, buf_size)) {
1322 res = -EFAULT;
1323 goto out_unlock;
1324 }
1325 res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
1326 if (res != 3) {
1327 res = -EFAULT;
1328 goto out_unlock;
1329 }
1330
1331 event_bitmap = libertas_get_events_bitmap(priv);
1332
1333 res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
1334 if (res < 0)
1335 goto out_unlock;
1336
1337 event = &pcmdptr->params.subscribe_event;
1338 event->action = cmd_act_set;
1339 pcmdptr->size = cpu_to_le16(S_DS_GEN +
1340 sizeof(struct cmd_ds_802_11_subscribe_event) +
1341 sizeof(struct mrvlietypes_snrthreshold));
1342 cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
1343 ptr = (u8*) pcmdptr+cmd_len;
1344 snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
1345 snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
1346 snr_threshold->header.len = 2;
1347 snr_threshold->snrvalue = cpu_to_le16(value);
1348 snr_threshold->snrfreq = cpu_to_le16(freq);
1349 event_bitmap |= subscribed ? 0x0020 : 0x0;
1350 event->events = event_bitmap;
1351
1352 libertas_queue_cmd(adapter, pcmdnode, 1);
1353 wake_up_interruptible(&priv->mainthread.waitq);
1354
1355 /* Sleep until response is generated by FW */
1356 wait_event_interruptible(pcmdnode->cmdwait_q,
1357 pcmdnode->cmdwaitqwoken);
1358
1359 pcmdptr = response_buf;
1360
1361 if (pcmdptr->result) {
1362 lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
1363 pcmdptr->result);
1364 kfree(response_buf);
1365 free_page(addr);
1366 return 0;
1367 }
1368
1369 if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
1370 lbs_pr_err("command response incorrect!\n");
1371 kfree(response_buf);
1372 free_page(addr);
1373 return 0;
1374 }
1375
1376 res = count;
1377out_unlock:
1378 free_page(addr);
1379 return res;
1380}
1381
1382static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
1383 size_t count, loff_t *ppos)
1384{
1385 wlan_private *priv = file->private_data;
1386 wlan_adapter *adapter = priv->adapter;
1387 struct wlan_offset_value offval;
1388 ssize_t pos = 0;
1389 int ret;
1390 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1391 char *buf = (char *)addr;
1392
1393 offval.offset = priv->mac_offset;
1394 offval.value = 0;
1395
1396 ret = libertas_prepare_and_send_command(priv,
1397 cmd_mac_reg_access, 0,
1398 cmd_option_waitforrsp, 0, &offval);
1399 mdelay(10);
1400 pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
1401 priv->mac_offset, adapter->offsetvalue.value);
1402
1403 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1404 free_page(addr);
1405 return ret;
1406}
1407
1408static ssize_t libertas_rdmac_write(struct file *file,
1409 const char __user *userbuf,
1410 size_t count, loff_t *ppos)
1411{
1412 wlan_private *priv = file->private_data;
1413 ssize_t res, buf_size;
1414 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1415 char *buf = (char *)addr;
1416
1417 buf_size = min(count, len - 1);
1418 if (copy_from_user(buf, userbuf, buf_size)) {
1419 res = -EFAULT;
1420 goto out_unlock;
1421 }
1422 priv->mac_offset = simple_strtoul((char *)buf, NULL, 16);
1423 res = count;
1424out_unlock:
1425 free_page(addr);
1426 return res;
1427}
1428
1429static ssize_t libertas_wrmac_write(struct file *file,
1430 const char __user *userbuf,
1431 size_t count, loff_t *ppos)
1432{
1433
1434 wlan_private *priv = file->private_data;
1435 ssize_t res, buf_size;
1436 u32 offset, value;
1437 struct wlan_offset_value offval;
1438 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1439 char *buf = (char *)addr;
1440
1441 buf_size = min(count, len - 1);
1442 if (copy_from_user(buf, userbuf, buf_size)) {
1443 res = -EFAULT;
1444 goto out_unlock;
1445 }
1446 res = sscanf(buf, "%x %x", &offset, &value);
1447 if (res != 2) {
1448 res = -EFAULT;
1449 goto out_unlock;
1450 }
1451
1452 offval.offset = offset;
1453 offval.value = value;
1454 res = libertas_prepare_and_send_command(priv,
1455 cmd_mac_reg_access, 1,
1456 cmd_option_waitforrsp, 0, &offval);
1457 mdelay(10);
1458
1459 res = count;
1460out_unlock:
1461 free_page(addr);
1462 return res;
1463}
1464
1465static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
1466 size_t count, loff_t *ppos)
1467{
1468 wlan_private *priv = file->private_data;
1469 wlan_adapter *adapter = priv->adapter;
1470 struct wlan_offset_value offval;
1471 ssize_t pos = 0;
1472 int ret;
1473 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1474 char *buf = (char *)addr;
1475
1476 offval.offset = priv->bbp_offset;
1477 offval.value = 0;
1478
1479 ret = libertas_prepare_and_send_command(priv,
1480 cmd_bbp_reg_access, 0,
1481 cmd_option_waitforrsp, 0, &offval);
1482 mdelay(10);
1483 pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
1484 priv->bbp_offset, adapter->offsetvalue.value);
1485
1486 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1487 free_page(addr);
1488
1489 return ret;
1490}
1491
1492static ssize_t libertas_rdbbp_write(struct file *file,
1493 const char __user *userbuf,
1494 size_t count, loff_t *ppos)
1495{
1496 wlan_private *priv = file->private_data;
1497 ssize_t res, buf_size;
1498 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1499 char *buf = (char *)addr;
1500
1501 buf_size = min(count, len - 1);
1502 if (copy_from_user(buf, userbuf, buf_size)) {
1503 res = -EFAULT;
1504 goto out_unlock;
1505 }
1506 priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16);
1507 res = count;
1508out_unlock:
1509 free_page(addr);
1510 return res;
1511}
1512
1513static ssize_t libertas_wrbbp_write(struct file *file,
1514 const char __user *userbuf,
1515 size_t count, loff_t *ppos)
1516{
1517
1518 wlan_private *priv = file->private_data;
1519 ssize_t res, buf_size;
1520 u32 offset, value;
1521 struct wlan_offset_value offval;
1522 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1523 char *buf = (char *)addr;
1524
1525 buf_size = min(count, len - 1);
1526 if (copy_from_user(buf, userbuf, buf_size)) {
1527 res = -EFAULT;
1528 goto out_unlock;
1529 }
1530 res = sscanf(buf, "%x %x", &offset, &value);
1531 if (res != 2) {
1532 res = -EFAULT;
1533 goto out_unlock;
1534 }
1535
1536 offval.offset = offset;
1537 offval.value = value;
1538 res = libertas_prepare_and_send_command(priv,
1539 cmd_bbp_reg_access, 1,
1540 cmd_option_waitforrsp, 0, &offval);
1541 mdelay(10);
1542
1543 res = count;
1544out_unlock:
1545 free_page(addr);
1546 return res;
1547}
1548
1549static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
1550 size_t count, loff_t *ppos)
1551{
1552 wlan_private *priv = file->private_data;
1553 wlan_adapter *adapter = priv->adapter;
1554 struct wlan_offset_value offval;
1555 ssize_t pos = 0;
1556 int ret;
1557 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1558 char *buf = (char *)addr;
1559
1560 offval.offset = priv->rf_offset;
1561 offval.value = 0;
1562
1563 ret = libertas_prepare_and_send_command(priv,
1564 cmd_rf_reg_access, 0,
1565 cmd_option_waitforrsp, 0, &offval);
1566 mdelay(10);
1567 pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
1568 priv->rf_offset, adapter->offsetvalue.value);
1569
1570 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
1571 free_page(addr);
1572
1573 return ret;
1574}
1575
1576static ssize_t libertas_rdrf_write(struct file *file,
1577 const char __user *userbuf,
1578 size_t count, loff_t *ppos)
1579{
1580 wlan_private *priv = file->private_data;
1581 ssize_t res, buf_size;
1582 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1583 char *buf = (char *)addr;
1584
1585 buf_size = min(count, len - 1);
1586 if (copy_from_user(buf, userbuf, buf_size)) {
1587 res = -EFAULT;
1588 goto out_unlock;
1589 }
1590 priv->rf_offset = simple_strtoul((char *)buf, NULL, 16);
1591 res = count;
1592out_unlock:
1593 free_page(addr);
1594 return res;
1595}
1596
1597static ssize_t libertas_wrrf_write(struct file *file,
1598 const char __user *userbuf,
1599 size_t count, loff_t *ppos)
1600{
1601
1602 wlan_private *priv = file->private_data;
1603 ssize_t res, buf_size;
1604 u32 offset, value;
1605 struct wlan_offset_value offval;
1606 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1607 char *buf = (char *)addr;
1608
1609 buf_size = min(count, len - 1);
1610 if (copy_from_user(buf, userbuf, buf_size)) {
1611 res = -EFAULT;
1612 goto out_unlock;
1613 }
1614 res = sscanf(buf, "%x %x", &offset, &value);
1615 if (res != 2) {
1616 res = -EFAULT;
1617 goto out_unlock;
1618 }
1619
1620 offval.offset = offset;
1621 offval.value = value;
1622 res = libertas_prepare_and_send_command(priv,
1623 cmd_rf_reg_access, 1,
1624 cmd_option_waitforrsp, 0, &offval);
1625 mdelay(10);
1626
1627 res = count;
1628out_unlock:
1629 free_page(addr);
1630 return res;
1631}
1632
1633#define FOPS(fread, fwrite) { \
1634 .owner = THIS_MODULE, \
1635 .open = open_file_generic, \
1636 .read = (fread), \
1637 .write = (fwrite), \
1638}
1639
1640struct libertas_debugfs_files {
1641 char *name;
1642 int perm;
1643 struct file_operations fops;
1644};
1645
Dan Williams5bdb3ef2007-05-10 23:08:05 -04001646static struct libertas_debugfs_files debugfs_files[] = {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001647 { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), },
1648 { "getscantable", 0444, FOPS(libertas_getscantable,
1649 write_file_dummy), },
1650 { "sleepparams", 0644, FOPS(libertas_sleepparams_read,
1651 libertas_sleepparams_write), },
1652 { "extscan", 0600, FOPS(NULL, libertas_extscan), },
1653 { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), },
1654};
1655
Dan Williams5bdb3ef2007-05-10 23:08:05 -04001656static struct libertas_debugfs_files debugfs_events_files[] = {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001657 {"low_rssi", 0644, FOPS(libertas_lowrssi_read,
1658 libertas_lowrssi_write), },
1659 {"low_snr", 0644, FOPS(libertas_lowsnr_read,
1660 libertas_lowsnr_write), },
1661 {"failure_count", 0644, FOPS(libertas_failcount_read,
1662 libertas_failcount_write), },
1663 {"beacon_missed", 0644, FOPS(libertas_bcnmiss_read,
1664 libertas_bcnmiss_write), },
1665 {"high_rssi", 0644, FOPS(libertas_highrssi_read,
1666 libertas_highrssi_write), },
1667 {"high_snr", 0644, FOPS(libertas_highsnr_read,
1668 libertas_highsnr_write), },
1669};
1670
Dan Williams5bdb3ef2007-05-10 23:08:05 -04001671static struct libertas_debugfs_files debugfs_regs_files[] = {
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001672 {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), },
1673 {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), },
1674 {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), },
1675 {"wrbbp", 0600, FOPS(NULL, libertas_wrbbp_write), },
1676 {"rdrf", 0644, FOPS(libertas_rdrf_read, libertas_rdrf_write), },
1677 {"wrrf", 0600, FOPS(NULL, libertas_wrrf_write), },
1678};
1679
1680void libertas_debugfs_init(void)
1681{
1682 if (!libertas_dir)
1683 libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
1684
1685 return;
1686}
1687
1688void libertas_debugfs_remove(void)
1689{
1690 if (libertas_dir)
1691 debugfs_remove(libertas_dir);
1692 return;
1693}
1694
1695void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
1696{
1697 int i;
1698 struct libertas_debugfs_files *files;
1699 if (!libertas_dir)
1700 goto exit;
1701
1702 priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
1703 if (!priv->debugfs_dir)
1704 goto exit;
1705
1706 for (i=0; i<ARRAY_SIZE(debugfs_files); i++) {
1707 files = &debugfs_files[i];
1708 priv->debugfs_files[i] = debugfs_create_file(files->name,
1709 files->perm,
1710 priv->debugfs_dir,
1711 priv,
1712 &files->fops);
1713 }
1714
1715 priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir);
1716 if (!priv->events_dir)
1717 goto exit;
1718
1719 for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) {
1720 files = &debugfs_events_files[i];
1721 priv->debugfs_events_files[i] = debugfs_create_file(files->name,
1722 files->perm,
1723 priv->events_dir,
1724 priv,
1725 &files->fops);
1726 }
1727
1728 priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir);
1729 if (!priv->regs_dir)
1730 goto exit;
1731
1732 for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) {
1733 files = &debugfs_regs_files[i];
1734 priv->debugfs_regs_files[i] = debugfs_create_file(files->name,
1735 files->perm,
1736 priv->regs_dir,
1737 priv,
1738 &files->fops);
1739 }
1740
1741#ifdef PROC_DEBUG
1742 libertas_debug_init(priv, dev);
1743#endif
1744exit:
1745 return;
1746}
1747
1748void libertas_debugfs_remove_one(wlan_private *priv)
1749{
1750 int i;
1751
1752 for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++)
1753 debugfs_remove(priv->debugfs_regs_files[i]);
1754
1755 debugfs_remove(priv->regs_dir);
1756
Holger Schurig0b7db952007-05-24 23:47:34 -04001757 for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001758 debugfs_remove(priv->debugfs_events_files[i]);
1759
1760 debugfs_remove(priv->events_dir);
1761#ifdef PROC_DEBUG
1762 debugfs_remove(priv->debugfs_debug);
1763#endif
1764 for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
1765 debugfs_remove(priv->debugfs_files[i]);
Holger Schurig0b7db952007-05-24 23:47:34 -04001766 debugfs_remove(priv->debugfs_dir);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001767}
1768
Holger Schurig46868202007-05-25 00:37:28 -04001769
1770
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001771/* debug entry */
1772
Holger Schurig46868202007-05-25 00:37:28 -04001773#ifdef PROC_DEBUG
1774
Tony Breedsd2f11e02007-03-09 13:11:46 +11001775#define item_size(n) (FIELD_SIZEOF(wlan_adapter, n))
1776#define item_addr(n) (offsetof(wlan_adapter, n))
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001777
Holger Schurig46868202007-05-25 00:37:28 -04001778
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001779struct debug_data {
1780 char name[32];
1781 u32 size;
Dan Williams4269e2a2007-05-10 23:10:18 -04001782 size_t addr;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001783};
1784
1785/* To debug any member of wlan_adapter, simply add one line here.
1786 */
1787static struct debug_data items[] = {
1788 {"intcounter", item_size(intcounter), item_addr(intcounter)},
1789 {"psmode", item_size(psmode), item_addr(psmode)},
1790 {"psstate", item_size(psstate), item_addr(psstate)},
1791};
1792
Tony Breedsd2f11e02007-03-09 13:11:46 +11001793static int num_of_items = ARRAY_SIZE(items);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001794
1795/**
1796 * @brief proc read function
1797 *
1798 * @param page pointer to buffer
1799 * @param s read data starting position
1800 * @param off offset
1801 * @param cnt counter
1802 * @param eof end of file flag
1803 * @param data data to output
1804 * @return number of output data
1805 */
1806static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
1807 size_t count, loff_t *ppos)
1808{
1809 int val = 0;
1810 size_t pos = 0;
1811 ssize_t res;
1812 char *p;
1813 int i;
1814 struct debug_data *d;
1815 unsigned long addr = get_zeroed_page(GFP_KERNEL);
1816 char *buf = (char *)addr;
1817
1818 p = buf;
1819
1820 d = (struct debug_data *)file->private_data;
1821
1822 for (i = 0; i < num_of_items; i++) {
1823 if (d[i].size == 1)
1824 val = *((u8 *) d[i].addr);
1825 else if (d[i].size == 2)
1826 val = *((u16 *) d[i].addr);
1827 else if (d[i].size == 4)
1828 val = *((u32 *) d[i].addr);
Dan Williams4269e2a2007-05-10 23:10:18 -04001829 else if (d[i].size == 8)
1830 val = *((u64 *) d[i].addr);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001831
1832 pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
1833 }
1834
1835 res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
1836
1837 free_page(addr);
1838 return res;
1839}
1840
1841/**
1842 * @brief proc write function
1843 *
1844 * @param f file pointer
1845 * @param buf pointer to data buffer
1846 * @param cnt data number to write
1847 * @param data data to write
1848 * @return number of data
1849 */
Dan Williams4269e2a2007-05-10 23:10:18 -04001850static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001851 size_t cnt, loff_t *ppos)
1852{
1853 int r, i;
1854 char *pdata;
1855 char *p;
1856 char *p0;
1857 char *p1;
1858 char *p2;
1859 struct debug_data *d = (struct debug_data *)f->private_data;
1860
1861 pdata = (char *)kmalloc(cnt, GFP_KERNEL);
1862 if (pdata == NULL)
1863 return 0;
1864
1865 if (copy_from_user(pdata, buf, cnt)) {
Holger Schurig9012b282007-05-25 11:27:16 -04001866 lbs_deb_debugfs("Copy from user failed\n");
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001867 kfree(pdata);
1868 return 0;
1869 }
1870
1871 p0 = pdata;
1872 for (i = 0; i < num_of_items; i++) {
1873 do {
1874 p = strstr(p0, d[i].name);
1875 if (p == NULL)
1876 break;
1877 p1 = strchr(p, '\n');
1878 if (p1 == NULL)
1879 break;
1880 p0 = p1++;
1881 p2 = strchr(p, '=');
1882 if (!p2)
1883 break;
1884 p2++;
Tony Breedsd2f11e02007-03-09 13:11:46 +11001885 r = simple_strtoul(p2, NULL, 0);
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001886 if (d[i].size == 1)
1887 *((u8 *) d[i].addr) = (u8) r;
1888 else if (d[i].size == 2)
1889 *((u16 *) d[i].addr) = (u16) r;
1890 else if (d[i].size == 4)
1891 *((u32 *) d[i].addr) = (u32) r;
Dan Williams4269e2a2007-05-10 23:10:18 -04001892 else if (d[i].size == 8)
1893 *((u64 *) d[i].addr) = (u64) r;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001894 break;
1895 } while (1);
1896 }
1897 kfree(pdata);
1898
Dan Williams4269e2a2007-05-10 23:10:18 -04001899 return (ssize_t)cnt;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001900}
1901
1902static struct file_operations libertas_debug_fops = {
1903 .owner = THIS_MODULE,
1904 .open = open_file_generic,
1905 .write = wlan_debugfs_write,
1906 .read = wlan_debugfs_read,
1907};
1908
1909/**
1910 * @brief create debug proc file
1911 *
1912 * @param priv pointer wlan_private
1913 * @param dev pointer net_device
1914 * @return N/A
1915 */
Holger Schurig46868202007-05-25 00:37:28 -04001916static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001917{
1918 int i;
1919
1920 if (!priv->debugfs_dir)
1921 return;
1922
1923 for (i = 0; i < num_of_items; i++)
Dan Williams4269e2a2007-05-10 23:10:18 -04001924 items[i].addr += (size_t) priv->adapter;
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001925
1926 priv->debugfs_debug = debugfs_create_file("debug", 0644,
1927 priv->debugfs_dir, &items[0],
1928 &libertas_debug_fops);
1929}
Holger Schurig46868202007-05-25 00:37:28 -04001930#endif
Marcelo Tosatti876c9d32007-02-10 12:25:27 -02001931