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