1 #include <linux/module.h>
2 #include <linux/dcache.h>
3 #include <linux/debugfs.h>
4 #include <linux/delay.h>
6 #include <linux/string.h>
7 #include <net/iw_handler.h>
14 static struct dentry
*lbs_dir
;
15 static char *szStates
[] = {
21 static void lbs_debug_init(struct lbs_private
*priv
, struct net_device
*dev
);
24 static int open_file_generic(struct inode
*inode
, struct file
*file
)
26 file
->private_data
= inode
->i_private
;
30 static ssize_t
write_file_dummy(struct file
*file
, const char __user
*buf
,
31 size_t count
, loff_t
*ppos
)
36 static const size_t len
= PAGE_SIZE
;
38 static ssize_t
lbs_dev_info(struct file
*file
, char __user
*userbuf
,
39 size_t count
, loff_t
*ppos
)
41 struct lbs_private
*priv
= file
->private_data
;
43 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
44 char *buf
= (char *)addr
;
47 pos
+= snprintf(buf
+pos
, len
-pos
, "state = %s\n",
48 szStates
[priv
->adapter
->connect_status
]);
49 pos
+= snprintf(buf
+pos
, len
-pos
, "region_code = %02x\n",
50 (u32
) priv
->adapter
->regioncode
);
52 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
59 static ssize_t
lbs_getscantable(struct file
*file
, char __user
*userbuf
,
60 size_t count
, loff_t
*ppos
)
62 struct lbs_private
*priv
= file
->private_data
;
64 int numscansdone
= 0, res
;
65 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
66 char *buf
= (char *)addr
;
68 struct bss_descriptor
* iter_bss
;
70 pos
+= snprintf(buf
+pos
, len
-pos
,
71 "# | ch | rssi | bssid | cap | Qual | SSID \n");
73 mutex_lock(&priv
->adapter
->lock
);
74 list_for_each_entry (iter_bss
, &priv
->adapter
->network_list
, list
) {
75 u16 ibss
= (iter_bss
->capability
& WLAN_CAPABILITY_IBSS
);
76 u16 privacy
= (iter_bss
->capability
& WLAN_CAPABILITY_PRIVACY
);
77 u16 spectrum_mgmt
= (iter_bss
->capability
& WLAN_CAPABILITY_SPECTRUM_MGMT
);
79 pos
+= snprintf(buf
+pos
, len
-pos
,
80 "%02u| %03d | %04ld | %s |",
81 numscansdone
, iter_bss
->channel
, iter_bss
->rssi
,
82 print_mac(mac
, iter_bss
->bssid
));
83 pos
+= snprintf(buf
+pos
, len
-pos
, " %04x-", iter_bss
->capability
);
84 pos
+= snprintf(buf
+pos
, len
-pos
, "%c%c%c |",
85 ibss
? 'A' : 'I', privacy
? 'P' : ' ',
86 spectrum_mgmt
? 'S' : ' ');
87 pos
+= snprintf(buf
+pos
, len
-pos
, " %04d |", SCAN_RSSI(iter_bss
->rssi
));
88 pos
+= snprintf(buf
+pos
, len
-pos
, " %s\n",
89 escape_essid(iter_bss
->ssid
, iter_bss
->ssid_len
));
93 mutex_unlock(&priv
->adapter
->lock
);
95 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
101 static ssize_t
lbs_sleepparams_write(struct file
*file
,
102 const char __user
*user_buf
, size_t count
,
105 struct lbs_private
*priv
= file
->private_data
;
106 ssize_t buf_size
, res
;
107 int p1
, p2
, p3
, p4
, p5
, p6
;
108 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
109 char *buf
= (char *)addr
;
111 buf_size
= min(count
, len
- 1);
112 if (copy_from_user(buf
, user_buf
, buf_size
)) {
116 res
= sscanf(buf
, "%d %d %d %d %d %d", &p1
, &p2
, &p3
, &p4
, &p5
, &p6
);
121 priv
->adapter
->sp
.sp_error
= p1
;
122 priv
->adapter
->sp
.sp_offset
= p2
;
123 priv
->adapter
->sp
.sp_stabletime
= p3
;
124 priv
->adapter
->sp
.sp_calcontrol
= p4
;
125 priv
->adapter
->sp
.sp_extsleepclk
= p5
;
126 priv
->adapter
->sp
.sp_reserved
= p6
;
128 res
= lbs_prepare_and_send_command(priv
,
129 CMD_802_11_SLEEP_PARAMS
,
131 CMD_OPTION_WAITFORRSP
, 0, NULL
);
143 static ssize_t
lbs_sleepparams_read(struct file
*file
, char __user
*userbuf
,
144 size_t count
, loff_t
*ppos
)
146 struct lbs_private
*priv
= file
->private_data
;
147 struct lbs_adapter
*adapter
= priv
->adapter
;
150 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
151 char *buf
= (char *)addr
;
153 res
= lbs_prepare_and_send_command(priv
,
154 CMD_802_11_SLEEP_PARAMS
,
156 CMD_OPTION_WAITFORRSP
, 0, NULL
);
162 pos
+= snprintf(buf
, len
, "%d %d %d %d %d %d\n", adapter
->sp
.sp_error
,
163 adapter
->sp
.sp_offset
, adapter
->sp
.sp_stabletime
,
164 adapter
->sp
.sp_calcontrol
, adapter
->sp
.sp_extsleepclk
,
165 adapter
->sp
.sp_reserved
);
167 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
174 static ssize_t
lbs_extscan(struct file
*file
, const char __user
*userbuf
,
175 size_t count
, loff_t
*ppos
)
177 struct lbs_private
*priv
= file
->private_data
;
178 ssize_t res
, buf_size
;
179 union iwreq_data wrqu
;
180 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
181 char *buf
= (char *)addr
;
183 buf_size
= min(count
, len
- 1);
184 if (copy_from_user(buf
, userbuf
, buf_size
)) {
189 lbs_send_specific_ssid_scan(priv
, buf
, strlen(buf
)-1, 0);
191 memset(&wrqu
, 0, sizeof(union iwreq_data
));
192 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
199 static void lbs_parse_bssid(char *buf
, size_t count
,
200 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
203 unsigned int mac
[ETH_ALEN
];
205 hold
= strstr(buf
, "bssid=");
209 sscanf(hold
, "%02x:%02x:%02x:%02x:%02x:%02x",
210 mac
, mac
+1, mac
+2, mac
+3, mac
+4, mac
+5);
211 memcpy(scan_cfg
->bssid
, mac
, ETH_ALEN
);
214 static void lbs_parse_ssid(char *buf
, size_t count
,
215 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
220 hold
= strstr(buf
, "ssid=");
224 end
= strchr(hold
, ' ');
226 end
= buf
+ count
- 1;
228 size
= min((size_t)IW_ESSID_MAX_SIZE
, (size_t) (end
- hold
));
229 strncpy(scan_cfg
->ssid
, hold
, size
);
234 static int lbs_parse_clear(char *buf
, size_t count
, const char *tag
)
239 hold
= strstr(buf
, tag
);
243 sscanf(hold
, "%d", &val
);
251 static int lbs_parse_dur(char *buf
, size_t count
,
252 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
257 hold
= strstr(buf
, "dur=");
261 sscanf(hold
, "%d", &val
);
266 static void lbs_parse_type(char *buf
, size_t count
,
267 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
272 hold
= strstr(buf
, "type=");
276 sscanf(hold
, "%d", &val
);
279 if (val
< 1 || val
> 3)
282 scan_cfg
->bsstype
= val
;
287 static ssize_t
lbs_setuserscan(struct file
*file
,
288 const char __user
*userbuf
,
289 size_t count
, loff_t
*ppos
)
291 struct lbs_private
*priv
= file
->private_data
;
292 ssize_t res
, buf_size
;
293 struct lbs_ioctl_user_scan_cfg
*scan_cfg
;
294 union iwreq_data wrqu
;
296 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
297 char *buf
= (char *)addr
;
299 scan_cfg
= kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg
), GFP_KERNEL
);
303 buf_size
= min(count
, len
- 1);
304 if (copy_from_user(buf
, userbuf
, buf_size
)) {
309 scan_cfg
->bsstype
= LBS_SCAN_BSS_TYPE_ANY
;
311 dur
= lbs_parse_dur(buf
, count
, scan_cfg
);
312 lbs_parse_bssid(buf
, count
, scan_cfg
);
313 scan_cfg
->clear_bssid
= lbs_parse_clear(buf
, count
, "clear_bssid=");
314 lbs_parse_ssid(buf
, count
, scan_cfg
);
315 scan_cfg
->clear_ssid
= lbs_parse_clear(buf
, count
, "clear_ssid=");
316 lbs_parse_type(buf
, count
, scan_cfg
);
318 lbs_scan_networks(priv
, scan_cfg
, 1);
319 wait_event_interruptible(priv
->adapter
->cmd_pending
,
320 !priv
->adapter
->nr_cmd_pending
);
322 memset(&wrqu
, 0x00, sizeof(union iwreq_data
));
323 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
333 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
334 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
335 * firmware. Here's an example:
336 * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
337 * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
338 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
340 * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
341 * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
342 * defined in mrvlietypes_thresholds
344 * This function searches in this TLV data chunk for a given TLV type
345 * and returns a pointer to the first data byte of the TLV, or to NULL
346 * if the TLV hasn't been found.
348 static void *lbs_tlv_find(u16 tlv_type
, const u8
*tlv
, u16 size
)
350 __le16 le_type
= cpu_to_le16(tlv_type
);
352 struct mrvlietypesheader
*tlv_h
;
355 tlv_h
= (struct mrvlietypesheader
*) tlv
;
356 if (tlv_h
->type
== le_type
)
360 length
= le16_to_cpu(tlv_h
->len
) +
361 sizeof(struct mrvlietypesheader
);
370 * This just gets the bitmap of currently subscribed events. Used when
371 * adding an additonal event subscription.
373 static u16
lbs_get_events_bitmap(struct lbs_private
*priv
)
377 struct cmd_ds_802_11_subscribe_event
*events
= kzalloc(
378 sizeof(struct cmd_ds_802_11_subscribe_event
),
381 res
= lbs_prepare_and_send_command(priv
,
382 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_GET
,
383 CMD_OPTION_WAITFORRSP
, 0, events
);
389 return le16_to_cpu(events
->events
);
393 static ssize_t
lbs_threshold_read(
394 u16 tlv_type
, u16 event_mask
,
395 struct file
*file
, char __user
*userbuf
,
396 size_t count
, loff_t
*ppos
)
398 struct lbs_private
*priv
= file
->private_data
;
401 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
402 char *buf
= (char *)addr
;
406 struct cmd_ds_802_11_subscribe_event
*events
= kzalloc(
407 sizeof(struct cmd_ds_802_11_subscribe_event
),
409 struct mrvlietypes_thresholds
*got
;
411 res
= lbs_prepare_and_send_command(priv
,
412 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_GET
,
413 CMD_OPTION_WAITFORRSP
, 0, events
);
419 got
= lbs_tlv_find(tlv_type
, events
->tlv
, sizeof(events
->tlv
));
427 pos
+= snprintf(buf
, len
, "%d %d %d\n", value
, freq
,
428 !!(le16_to_cpu(events
->events
) & event_mask
));
430 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
437 static ssize_t
lbs_threshold_write(
438 u16 tlv_type
, u16 event_mask
,
440 const char __user
*userbuf
,
441 size_t count
, loff_t
*ppos
)
443 struct lbs_private
*priv
= file
->private_data
;
444 ssize_t res
, buf_size
;
445 int value
, freq
, curr_mask
, new_mask
;
446 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
447 char *buf
= (char *)addr
;
448 struct cmd_ds_802_11_subscribe_event
*events
;
450 buf_size
= min(count
, len
- 1);
451 if (copy_from_user(buf
, userbuf
, buf_size
)) {
455 res
= sscanf(buf
, "%d %d %d", &value
, &freq
, &new_mask
);
460 curr_mask
= lbs_get_events_bitmap(priv
);
463 new_mask
= curr_mask
| event_mask
;
465 new_mask
= curr_mask
& ~event_mask
;
467 /* Now everything is set and we can send stuff down to the firmware */
469 sizeof(struct cmd_ds_802_11_subscribe_event
),
472 struct mrvlietypes_thresholds
*tlv
=
473 (struct mrvlietypes_thresholds
*) events
->tlv
;
474 events
->action
= cpu_to_le16(CMD_ACT_SET
);
475 events
->events
= cpu_to_le16(new_mask
);
476 tlv
->header
.type
= cpu_to_le16(tlv_type
);
477 tlv
->header
.len
= cpu_to_le16(
478 sizeof(struct mrvlietypes_thresholds
) -
479 sizeof(struct mrvlietypesheader
));
481 if (tlv_type
!= TLV_TYPE_BCNMISS
)
483 lbs_prepare_and_send_command(priv
,
484 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_SET
,
485 CMD_OPTION_WAITFORRSP
, 0, events
);
496 static ssize_t
lbs_lowrssi_read(
497 struct file
*file
, char __user
*userbuf
,
498 size_t count
, loff_t
*ppos
)
500 return lbs_threshold_read(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
501 file
, userbuf
, count
, ppos
);
505 static ssize_t
lbs_lowrssi_write(
506 struct file
*file
, const char __user
*userbuf
,
507 size_t count
, loff_t
*ppos
)
509 return lbs_threshold_write(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
510 file
, userbuf
, count
, ppos
);
514 static ssize_t
lbs_lowsnr_read(
515 struct file
*file
, char __user
*userbuf
,
516 size_t count
, loff_t
*ppos
)
518 return lbs_threshold_read(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
519 file
, userbuf
, count
, ppos
);
523 static ssize_t
lbs_lowsnr_write(
524 struct file
*file
, const char __user
*userbuf
,
525 size_t count
, loff_t
*ppos
)
527 return lbs_threshold_write(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
528 file
, userbuf
, count
, ppos
);
532 static ssize_t
lbs_failcount_read(
533 struct file
*file
, char __user
*userbuf
,
534 size_t count
, loff_t
*ppos
)
536 return lbs_threshold_read(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
537 file
, userbuf
, count
, ppos
);
541 static ssize_t
lbs_failcount_write(
542 struct file
*file
, const char __user
*userbuf
,
543 size_t count
, loff_t
*ppos
)
545 return lbs_threshold_write(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
546 file
, userbuf
, count
, ppos
);
550 static ssize_t
lbs_highrssi_read(
551 struct file
*file
, char __user
*userbuf
,
552 size_t count
, loff_t
*ppos
)
554 return lbs_threshold_read(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
555 file
, userbuf
, count
, ppos
);
559 static ssize_t
lbs_highrssi_write(
560 struct file
*file
, const char __user
*userbuf
,
561 size_t count
, loff_t
*ppos
)
563 return lbs_threshold_write(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
564 file
, userbuf
, count
, ppos
);
568 static ssize_t
lbs_highsnr_read(
569 struct file
*file
, char __user
*userbuf
,
570 size_t count
, loff_t
*ppos
)
572 return lbs_threshold_read(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
573 file
, userbuf
, count
, ppos
);
577 static ssize_t
lbs_highsnr_write(
578 struct file
*file
, const char __user
*userbuf
,
579 size_t count
, loff_t
*ppos
)
581 return lbs_threshold_write(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
582 file
, userbuf
, count
, ppos
);
585 static ssize_t
lbs_bcnmiss_read(
586 struct file
*file
, char __user
*userbuf
,
587 size_t count
, loff_t
*ppos
)
589 return lbs_threshold_read(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
590 file
, userbuf
, count
, ppos
);
594 static ssize_t
lbs_bcnmiss_write(
595 struct file
*file
, const char __user
*userbuf
,
596 size_t count
, loff_t
*ppos
)
598 return lbs_threshold_write(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
599 file
, userbuf
, count
, ppos
);
609 static ssize_t
lbs_rdmac_read(struct file
*file
, char __user
*userbuf
,
610 size_t count
, loff_t
*ppos
)
612 struct lbs_private
*priv
= file
->private_data
;
613 struct lbs_adapter
*adapter
= priv
->adapter
;
614 struct lbs_offset_value offval
;
617 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
618 char *buf
= (char *)addr
;
620 offval
.offset
= priv
->mac_offset
;
623 ret
= lbs_prepare_and_send_command(priv
,
624 CMD_MAC_REG_ACCESS
, 0,
625 CMD_OPTION_WAITFORRSP
, 0, &offval
);
627 pos
+= snprintf(buf
+pos
, len
-pos
, "MAC[0x%x] = 0x%08x\n",
628 priv
->mac_offset
, adapter
->offsetvalue
.value
);
630 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
635 static ssize_t
lbs_rdmac_write(struct file
*file
,
636 const char __user
*userbuf
,
637 size_t count
, loff_t
*ppos
)
639 struct lbs_private
*priv
= file
->private_data
;
640 ssize_t res
, buf_size
;
641 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
642 char *buf
= (char *)addr
;
644 buf_size
= min(count
, len
- 1);
645 if (copy_from_user(buf
, userbuf
, buf_size
)) {
649 priv
->mac_offset
= simple_strtoul((char *)buf
, NULL
, 16);
656 static ssize_t
lbs_wrmac_write(struct file
*file
,
657 const char __user
*userbuf
,
658 size_t count
, loff_t
*ppos
)
661 struct lbs_private
*priv
= file
->private_data
;
662 ssize_t res
, buf_size
;
664 struct lbs_offset_value offval
;
665 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
666 char *buf
= (char *)addr
;
668 buf_size
= min(count
, len
- 1);
669 if (copy_from_user(buf
, userbuf
, buf_size
)) {
673 res
= sscanf(buf
, "%x %x", &offset
, &value
);
679 offval
.offset
= offset
;
680 offval
.value
= value
;
681 res
= lbs_prepare_and_send_command(priv
,
682 CMD_MAC_REG_ACCESS
, 1,
683 CMD_OPTION_WAITFORRSP
, 0, &offval
);
692 static ssize_t
lbs_rdbbp_read(struct file
*file
, char __user
*userbuf
,
693 size_t count
, loff_t
*ppos
)
695 struct lbs_private
*priv
= file
->private_data
;
696 struct lbs_adapter
*adapter
= priv
->adapter
;
697 struct lbs_offset_value offval
;
700 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
701 char *buf
= (char *)addr
;
703 offval
.offset
= priv
->bbp_offset
;
706 ret
= lbs_prepare_and_send_command(priv
,
707 CMD_BBP_REG_ACCESS
, 0,
708 CMD_OPTION_WAITFORRSP
, 0, &offval
);
710 pos
+= snprintf(buf
+pos
, len
-pos
, "BBP[0x%x] = 0x%08x\n",
711 priv
->bbp_offset
, adapter
->offsetvalue
.value
);
713 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
719 static ssize_t
lbs_rdbbp_write(struct file
*file
,
720 const char __user
*userbuf
,
721 size_t count
, loff_t
*ppos
)
723 struct lbs_private
*priv
= file
->private_data
;
724 ssize_t res
, buf_size
;
725 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
726 char *buf
= (char *)addr
;
728 buf_size
= min(count
, len
- 1);
729 if (copy_from_user(buf
, userbuf
, buf_size
)) {
733 priv
->bbp_offset
= simple_strtoul((char *)buf
, NULL
, 16);
740 static ssize_t
lbs_wrbbp_write(struct file
*file
,
741 const char __user
*userbuf
,
742 size_t count
, loff_t
*ppos
)
745 struct lbs_private
*priv
= file
->private_data
;
746 ssize_t res
, buf_size
;
748 struct lbs_offset_value offval
;
749 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
750 char *buf
= (char *)addr
;
752 buf_size
= min(count
, len
- 1);
753 if (copy_from_user(buf
, userbuf
, buf_size
)) {
757 res
= sscanf(buf
, "%x %x", &offset
, &value
);
763 offval
.offset
= offset
;
764 offval
.value
= value
;
765 res
= lbs_prepare_and_send_command(priv
,
766 CMD_BBP_REG_ACCESS
, 1,
767 CMD_OPTION_WAITFORRSP
, 0, &offval
);
776 static ssize_t
lbs_rdrf_read(struct file
*file
, char __user
*userbuf
,
777 size_t count
, loff_t
*ppos
)
779 struct lbs_private
*priv
= file
->private_data
;
780 struct lbs_adapter
*adapter
= priv
->adapter
;
781 struct lbs_offset_value offval
;
784 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
785 char *buf
= (char *)addr
;
787 offval
.offset
= priv
->rf_offset
;
790 ret
= lbs_prepare_and_send_command(priv
,
791 CMD_RF_REG_ACCESS
, 0,
792 CMD_OPTION_WAITFORRSP
, 0, &offval
);
794 pos
+= snprintf(buf
+pos
, len
-pos
, "RF[0x%x] = 0x%08x\n",
795 priv
->rf_offset
, adapter
->offsetvalue
.value
);
797 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
803 static ssize_t
lbs_rdrf_write(struct file
*file
,
804 const char __user
*userbuf
,
805 size_t count
, loff_t
*ppos
)
807 struct lbs_private
*priv
= file
->private_data
;
808 ssize_t res
, buf_size
;
809 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
810 char *buf
= (char *)addr
;
812 buf_size
= min(count
, len
- 1);
813 if (copy_from_user(buf
, userbuf
, buf_size
)) {
817 priv
->rf_offset
= simple_strtoul((char *)buf
, NULL
, 16);
824 static ssize_t
lbs_wrrf_write(struct file
*file
,
825 const char __user
*userbuf
,
826 size_t count
, loff_t
*ppos
)
829 struct lbs_private
*priv
= file
->private_data
;
830 ssize_t res
, buf_size
;
832 struct lbs_offset_value offval
;
833 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
834 char *buf
= (char *)addr
;
836 buf_size
= min(count
, len
- 1);
837 if (copy_from_user(buf
, userbuf
, buf_size
)) {
841 res
= sscanf(buf
, "%x %x", &offset
, &value
);
847 offval
.offset
= offset
;
848 offval
.value
= value
;
849 res
= lbs_prepare_and_send_command(priv
,
850 CMD_RF_REG_ACCESS
, 1,
851 CMD_OPTION_WAITFORRSP
, 0, &offval
);
860 #define FOPS(fread, fwrite) { \
861 .owner = THIS_MODULE, \
862 .open = open_file_generic, \
867 struct lbs_debugfs_files
{
870 struct file_operations fops
;
873 static struct lbs_debugfs_files debugfs_files
[] = {
874 { "info", 0444, FOPS(lbs_dev_info
, write_file_dummy
), },
875 { "getscantable", 0444, FOPS(lbs_getscantable
,
876 write_file_dummy
), },
877 { "sleepparams", 0644, FOPS(lbs_sleepparams_read
,
878 lbs_sleepparams_write
), },
879 { "extscan", 0600, FOPS(NULL
, lbs_extscan
), },
880 { "setuserscan", 0600, FOPS(NULL
, lbs_setuserscan
), },
883 static struct lbs_debugfs_files debugfs_events_files
[] = {
884 {"low_rssi", 0644, FOPS(lbs_lowrssi_read
,
885 lbs_lowrssi_write
), },
886 {"low_snr", 0644, FOPS(lbs_lowsnr_read
,
887 lbs_lowsnr_write
), },
888 {"failure_count", 0644, FOPS(lbs_failcount_read
,
889 lbs_failcount_write
), },
890 {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read
,
891 lbs_bcnmiss_write
), },
892 {"high_rssi", 0644, FOPS(lbs_highrssi_read
,
893 lbs_highrssi_write
), },
894 {"high_snr", 0644, FOPS(lbs_highsnr_read
,
895 lbs_highsnr_write
), },
898 static struct lbs_debugfs_files debugfs_regs_files
[] = {
899 {"rdmac", 0644, FOPS(lbs_rdmac_read
, lbs_rdmac_write
), },
900 {"wrmac", 0600, FOPS(NULL
, lbs_wrmac_write
), },
901 {"rdbbp", 0644, FOPS(lbs_rdbbp_read
, lbs_rdbbp_write
), },
902 {"wrbbp", 0600, FOPS(NULL
, lbs_wrbbp_write
), },
903 {"rdrf", 0644, FOPS(lbs_rdrf_read
, lbs_rdrf_write
), },
904 {"wrrf", 0600, FOPS(NULL
, lbs_wrrf_write
), },
907 void lbs_debugfs_init(void)
910 lbs_dir
= debugfs_create_dir("lbs_wireless", NULL
);
915 void lbs_debugfs_remove(void)
918 debugfs_remove(lbs_dir
);
922 void lbs_debugfs_init_one(struct lbs_private
*priv
, struct net_device
*dev
)
925 struct lbs_debugfs_files
*files
;
929 priv
->debugfs_dir
= debugfs_create_dir(dev
->name
, lbs_dir
);
930 if (!priv
->debugfs_dir
)
933 for (i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++) {
934 files
= &debugfs_files
[i
];
935 priv
->debugfs_files
[i
] = debugfs_create_file(files
->name
,
942 priv
->events_dir
= debugfs_create_dir("subscribed_events", priv
->debugfs_dir
);
943 if (!priv
->events_dir
)
946 for (i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++) {
947 files
= &debugfs_events_files
[i
];
948 priv
->debugfs_events_files
[i
] = debugfs_create_file(files
->name
,
955 priv
->regs_dir
= debugfs_create_dir("registers", priv
->debugfs_dir
);
959 for (i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++) {
960 files
= &debugfs_regs_files
[i
];
961 priv
->debugfs_regs_files
[i
] = debugfs_create_file(files
->name
,
969 lbs_debug_init(priv
, dev
);
975 void lbs_debugfs_remove_one(struct lbs_private
*priv
)
979 for(i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++)
980 debugfs_remove(priv
->debugfs_regs_files
[i
]);
982 debugfs_remove(priv
->regs_dir
);
984 for(i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++)
985 debugfs_remove(priv
->debugfs_events_files
[i
]);
987 debugfs_remove(priv
->events_dir
);
989 debugfs_remove(priv
->debugfs_debug
);
991 for(i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++)
992 debugfs_remove(priv
->debugfs_files
[i
]);
993 debugfs_remove(priv
->debugfs_dir
);
1002 #define item_size(n) (FIELD_SIZEOF(struct lbs_adapter, n))
1003 #define item_addr(n) (offsetof(struct lbs_adapter, n))
1012 /* To debug any member of struct lbs_adapter, simply add one line here.
1014 static struct debug_data items
[] = {
1015 {"intcounter", item_size(intcounter
), item_addr(intcounter
)},
1016 {"psmode", item_size(psmode
), item_addr(psmode
)},
1017 {"psstate", item_size(psstate
), item_addr(psstate
)},
1020 static int num_of_items
= ARRAY_SIZE(items
);
1023 * @brief proc read function
1025 * @param page pointer to buffer
1026 * @param s read data starting position
1028 * @param cnt counter
1029 * @param eof end of file flag
1030 * @param data data to output
1031 * @return number of output data
1033 static ssize_t
lbs_debugfs_read(struct file
*file
, char __user
*userbuf
,
1034 size_t count
, loff_t
*ppos
)
1041 struct debug_data
*d
;
1042 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
1043 char *buf
= (char *)addr
;
1047 d
= (struct debug_data
*)file
->private_data
;
1049 for (i
= 0; i
< num_of_items
; i
++) {
1051 val
= *((u8
*) d
[i
].addr
);
1052 else if (d
[i
].size
== 2)
1053 val
= *((u16
*) d
[i
].addr
);
1054 else if (d
[i
].size
== 4)
1055 val
= *((u32
*) d
[i
].addr
);
1056 else if (d
[i
].size
== 8)
1057 val
= *((u64
*) d
[i
].addr
);
1059 pos
+= sprintf(p
+ pos
, "%s=%d\n", d
[i
].name
, val
);
1062 res
= simple_read_from_buffer(userbuf
, count
, ppos
, p
, pos
);
1069 * @brief proc write function
1071 * @param f file pointer
1072 * @param buf pointer to data buffer
1073 * @param cnt data number to write
1074 * @param data data to write
1075 * @return number of data
1077 static ssize_t
lbs_debugfs_write(struct file
*f
, const char __user
*buf
,
1078 size_t cnt
, loff_t
*ppos
)
1086 struct debug_data
*d
= (struct debug_data
*)f
->private_data
;
1088 pdata
= kmalloc(cnt
, GFP_KERNEL
);
1092 if (copy_from_user(pdata
, buf
, cnt
)) {
1093 lbs_deb_debugfs("Copy from user failed\n");
1099 for (i
= 0; i
< num_of_items
; i
++) {
1101 p
= strstr(p0
, d
[i
].name
);
1104 p1
= strchr(p
, '\n');
1108 p2
= strchr(p
, '=');
1112 r
= simple_strtoul(p2
, NULL
, 0);
1114 *((u8
*) d
[i
].addr
) = (u8
) r
;
1115 else if (d
[i
].size
== 2)
1116 *((u16
*) d
[i
].addr
) = (u16
) r
;
1117 else if (d
[i
].size
== 4)
1118 *((u32
*) d
[i
].addr
) = (u32
) r
;
1119 else if (d
[i
].size
== 8)
1120 *((u64
*) d
[i
].addr
) = (u64
) r
;
1126 return (ssize_t
)cnt
;
1129 static struct file_operations lbs_debug_fops
= {
1130 .owner
= THIS_MODULE
,
1131 .open
= open_file_generic
,
1132 .write
= lbs_debugfs_write
,
1133 .read
= lbs_debugfs_read
,
1137 * @brief create debug proc file
1139 * @param priv pointer struct lbs_private
1140 * @param dev pointer net_device
1143 static void lbs_debug_init(struct lbs_private
*priv
, struct net_device
*dev
)
1147 if (!priv
->debugfs_dir
)
1150 for (i
= 0; i
< num_of_items
; i
++)
1151 items
[i
].addr
+= (size_t) priv
->adapter
;
1153 priv
->debugfs_debug
= debugfs_create_file("debug", 0644,
1154 priv
->debugfs_dir
, &items
[0],