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
->connect_status
]);
49 pos
+= snprintf(buf
+pos
, len
-pos
, "region_code = %02x\n",
50 (u32
) priv
->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
->lock
);
74 list_for_each_entry (iter_bss
, &priv
->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
->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
->sp
.sp_error
= p1
;
122 priv
->sp
.sp_offset
= p2
;
123 priv
->sp
.sp_stabletime
= p3
;
124 priv
->sp
.sp_calcontrol
= p4
;
125 priv
->sp
.sp_extsleepclk
= p5
;
126 priv
->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
;
149 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
150 char *buf
= (char *)addr
;
152 res
= lbs_prepare_and_send_command(priv
,
153 CMD_802_11_SLEEP_PARAMS
,
155 CMD_OPTION_WAITFORRSP
, 0, NULL
);
161 pos
+= snprintf(buf
, len
, "%d %d %d %d %d %d\n", priv
->sp
.sp_error
,
162 priv
->sp
.sp_offset
, priv
->sp
.sp_stabletime
,
163 priv
->sp
.sp_calcontrol
, priv
->sp
.sp_extsleepclk
,
164 priv
->sp
.sp_reserved
);
166 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
173 static ssize_t
lbs_extscan(struct file
*file
, const char __user
*userbuf
,
174 size_t count
, loff_t
*ppos
)
176 struct lbs_private
*priv
= file
->private_data
;
177 ssize_t res
, buf_size
;
178 union iwreq_data wrqu
;
179 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
180 char *buf
= (char *)addr
;
182 buf_size
= min(count
, len
- 1);
183 if (copy_from_user(buf
, userbuf
, buf_size
)) {
188 lbs_send_specific_ssid_scan(priv
, buf
, strlen(buf
)-1, 0);
190 memset(&wrqu
, 0, sizeof(union iwreq_data
));
191 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
198 static void lbs_parse_bssid(char *buf
, size_t count
,
199 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
202 unsigned int mac
[ETH_ALEN
];
204 hold
= strstr(buf
, "bssid=");
208 sscanf(hold
, MAC_FMT
, mac
, mac
+1, mac
+2, mac
+3, mac
+4, mac
+5);
209 memcpy(scan_cfg
->bssid
, mac
, ETH_ALEN
);
212 static void lbs_parse_ssid(char *buf
, size_t count
,
213 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
218 hold
= strstr(buf
, "ssid=");
222 end
= strchr(hold
, ' ');
224 end
= buf
+ count
- 1;
226 size
= min((size_t)IW_ESSID_MAX_SIZE
, (size_t) (end
- hold
));
227 strncpy(scan_cfg
->ssid
, hold
, size
);
232 static int lbs_parse_clear(char *buf
, size_t count
, const char *tag
)
237 hold
= strstr(buf
, tag
);
241 sscanf(hold
, "%d", &val
);
249 static int lbs_parse_dur(char *buf
, size_t count
,
250 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
255 hold
= strstr(buf
, "dur=");
259 sscanf(hold
, "%d", &val
);
264 static void lbs_parse_type(char *buf
, size_t count
,
265 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
270 hold
= strstr(buf
, "type=");
274 sscanf(hold
, "%d", &val
);
277 if (val
< 1 || val
> 3)
280 scan_cfg
->bsstype
= val
;
285 static ssize_t
lbs_setuserscan(struct file
*file
,
286 const char __user
*userbuf
,
287 size_t count
, loff_t
*ppos
)
289 struct lbs_private
*priv
= file
->private_data
;
290 ssize_t res
, buf_size
;
291 struct lbs_ioctl_user_scan_cfg
*scan_cfg
;
292 union iwreq_data wrqu
;
294 char *buf
= (char *)get_zeroed_page(GFP_KERNEL
);
299 buf_size
= min(count
, len
- 1);
300 if (copy_from_user(buf
, userbuf
, buf_size
)) {
305 scan_cfg
= kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg
), GFP_KERNEL
);
312 scan_cfg
->bsstype
= LBS_SCAN_BSS_TYPE_ANY
;
314 dur
= lbs_parse_dur(buf
, count
, scan_cfg
);
315 lbs_parse_bssid(buf
, count
, scan_cfg
);
316 scan_cfg
->clear_bssid
= lbs_parse_clear(buf
, count
, "clear_bssid=");
317 lbs_parse_ssid(buf
, count
, scan_cfg
);
318 scan_cfg
->clear_ssid
= lbs_parse_clear(buf
, count
, "clear_ssid=");
319 lbs_parse_type(buf
, count
, scan_cfg
);
321 lbs_scan_networks(priv
, scan_cfg
, 1);
322 wait_event_interruptible(priv
->cmd_pending
,
323 priv
->surpriseremoved
|| !priv
->last_scanned_channel
);
325 if (priv
->surpriseremoved
)
328 memset(&wrqu
, 0x00, sizeof(union iwreq_data
));
329 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
334 free_page((unsigned long)buf
);
340 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
341 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
342 * firmware. Here's an example:
343 * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
344 * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
345 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
347 * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
348 * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
349 * defined in mrvlietypes_thresholds
351 * This function searches in this TLV data chunk for a given TLV type
352 * and returns a pointer to the first data byte of the TLV, or to NULL
353 * if the TLV hasn't been found.
355 static void *lbs_tlv_find(u16 tlv_type
, const u8
*tlv
, u16 size
)
357 __le16 le_type
= cpu_to_le16(tlv_type
);
359 struct mrvlietypesheader
*tlv_h
;
362 tlv_h
= (struct mrvlietypesheader
*) tlv
;
363 if (tlv_h
->type
== le_type
)
367 length
= le16_to_cpu(tlv_h
->len
) +
368 sizeof(struct mrvlietypesheader
);
377 * This just gets the bitmap of currently subscribed events. Used when
378 * adding an additonal event subscription.
380 static u16
lbs_get_events_bitmap(struct lbs_private
*priv
)
384 struct cmd_ds_802_11_subscribe_event
*events
= kzalloc(
385 sizeof(struct cmd_ds_802_11_subscribe_event
),
388 res
= lbs_prepare_and_send_command(priv
,
389 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_GET
,
390 CMD_OPTION_WAITFORRSP
, 0, events
);
396 return le16_to_cpu(events
->events
);
400 static ssize_t
lbs_threshold_read(
401 u16 tlv_type
, u16 event_mask
,
402 struct file
*file
, char __user
*userbuf
,
403 size_t count
, loff_t
*ppos
)
405 struct lbs_private
*priv
= file
->private_data
;
408 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
409 char *buf
= (char *)addr
;
414 struct cmd_ds_802_11_subscribe_event
*subscribed
= kzalloc(
415 sizeof(struct cmd_ds_802_11_subscribe_event
),
417 struct mrvlietypes_thresholds
*got
;
419 res
= lbs_prepare_and_send_command(priv
,
420 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_GET
,
421 CMD_OPTION_WAITFORRSP
, 0, subscribed
);
427 got
= lbs_tlv_find(tlv_type
, subscribed
->tlv
, sizeof(subscribed
->tlv
));
431 events
= le16_to_cpu(subscribed
->events
);
436 pos
+= snprintf(buf
, len
, "%d %d %d\n", value
, freq
,
437 !!(events
& event_mask
));
439 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
446 static ssize_t
lbs_threshold_write(
447 u16 tlv_type
, u16 event_mask
,
449 const char __user
*userbuf
,
450 size_t count
, loff_t
*ppos
)
452 struct lbs_private
*priv
= file
->private_data
;
453 ssize_t res
, buf_size
;
454 int value
, freq
, curr_mask
, new_mask
;
455 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
456 char *buf
= (char *)addr
;
457 struct cmd_ds_802_11_subscribe_event
*events
;
459 buf_size
= min(count
, len
- 1);
460 if (copy_from_user(buf
, userbuf
, buf_size
)) {
464 res
= sscanf(buf
, "%d %d %d", &value
, &freq
, &new_mask
);
469 curr_mask
= lbs_get_events_bitmap(priv
);
472 new_mask
= curr_mask
| event_mask
;
474 new_mask
= curr_mask
& ~event_mask
;
476 /* Now everything is set and we can send stuff down to the firmware */
478 sizeof(struct cmd_ds_802_11_subscribe_event
),
481 struct mrvlietypes_thresholds
*tlv
=
482 (struct mrvlietypes_thresholds
*) events
->tlv
;
483 events
->action
= cpu_to_le16(CMD_ACT_SET
);
484 events
->events
= cpu_to_le16(new_mask
);
485 tlv
->header
.type
= cpu_to_le16(tlv_type
);
486 tlv
->header
.len
= cpu_to_le16(
487 sizeof(struct mrvlietypes_thresholds
) -
488 sizeof(struct mrvlietypesheader
));
490 if (tlv_type
!= TLV_TYPE_BCNMISS
)
492 lbs_prepare_and_send_command(priv
,
493 CMD_802_11_SUBSCRIBE_EVENT
, CMD_ACT_SET
,
494 CMD_OPTION_WAITFORRSP
, 0, events
);
505 static ssize_t
lbs_lowrssi_read(
506 struct file
*file
, char __user
*userbuf
,
507 size_t count
, loff_t
*ppos
)
509 return lbs_threshold_read(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
510 file
, userbuf
, count
, ppos
);
514 static ssize_t
lbs_lowrssi_write(
515 struct file
*file
, const char __user
*userbuf
,
516 size_t count
, loff_t
*ppos
)
518 return lbs_threshold_write(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
519 file
, userbuf
, count
, ppos
);
523 static ssize_t
lbs_lowsnr_read(
524 struct file
*file
, char __user
*userbuf
,
525 size_t count
, loff_t
*ppos
)
527 return lbs_threshold_read(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
528 file
, userbuf
, count
, ppos
);
532 static ssize_t
lbs_lowsnr_write(
533 struct file
*file
, const char __user
*userbuf
,
534 size_t count
, loff_t
*ppos
)
536 return lbs_threshold_write(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
537 file
, userbuf
, count
, ppos
);
541 static ssize_t
lbs_failcount_read(
542 struct file
*file
, char __user
*userbuf
,
543 size_t count
, loff_t
*ppos
)
545 return lbs_threshold_read(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
546 file
, userbuf
, count
, ppos
);
550 static ssize_t
lbs_failcount_write(
551 struct file
*file
, const char __user
*userbuf
,
552 size_t count
, loff_t
*ppos
)
554 return lbs_threshold_write(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
555 file
, userbuf
, count
, ppos
);
559 static ssize_t
lbs_highrssi_read(
560 struct file
*file
, char __user
*userbuf
,
561 size_t count
, loff_t
*ppos
)
563 return lbs_threshold_read(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
564 file
, userbuf
, count
, ppos
);
568 static ssize_t
lbs_highrssi_write(
569 struct file
*file
, const char __user
*userbuf
,
570 size_t count
, loff_t
*ppos
)
572 return lbs_threshold_write(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
573 file
, userbuf
, count
, ppos
);
577 static ssize_t
lbs_highsnr_read(
578 struct file
*file
, char __user
*userbuf
,
579 size_t count
, loff_t
*ppos
)
581 return lbs_threshold_read(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
582 file
, userbuf
, count
, ppos
);
586 static ssize_t
lbs_highsnr_write(
587 struct file
*file
, const char __user
*userbuf
,
588 size_t count
, loff_t
*ppos
)
590 return lbs_threshold_write(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
591 file
, userbuf
, count
, ppos
);
594 static ssize_t
lbs_bcnmiss_read(
595 struct file
*file
, char __user
*userbuf
,
596 size_t count
, loff_t
*ppos
)
598 return lbs_threshold_read(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
599 file
, userbuf
, count
, ppos
);
603 static ssize_t
lbs_bcnmiss_write(
604 struct file
*file
, const char __user
*userbuf
,
605 size_t count
, loff_t
*ppos
)
607 return lbs_threshold_write(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
608 file
, userbuf
, count
, ppos
);
618 static ssize_t
lbs_rdmac_read(struct file
*file
, char __user
*userbuf
,
619 size_t count
, loff_t
*ppos
)
621 struct lbs_private
*priv
= file
->private_data
;
622 struct lbs_offset_value offval
;
625 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
626 char *buf
= (char *)addr
;
628 offval
.offset
= priv
->mac_offset
;
631 ret
= lbs_prepare_and_send_command(priv
,
632 CMD_MAC_REG_ACCESS
, 0,
633 CMD_OPTION_WAITFORRSP
, 0, &offval
);
635 pos
+= snprintf(buf
+pos
, len
-pos
, "MAC[0x%x] = 0x%08x\n",
636 priv
->mac_offset
, priv
->offsetvalue
.value
);
638 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
643 static ssize_t
lbs_rdmac_write(struct file
*file
,
644 const char __user
*userbuf
,
645 size_t count
, loff_t
*ppos
)
647 struct lbs_private
*priv
= file
->private_data
;
648 ssize_t res
, buf_size
;
649 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
650 char *buf
= (char *)addr
;
652 buf_size
= min(count
, len
- 1);
653 if (copy_from_user(buf
, userbuf
, buf_size
)) {
657 priv
->mac_offset
= simple_strtoul((char *)buf
, NULL
, 16);
664 static ssize_t
lbs_wrmac_write(struct file
*file
,
665 const char __user
*userbuf
,
666 size_t count
, loff_t
*ppos
)
669 struct lbs_private
*priv
= file
->private_data
;
670 ssize_t res
, buf_size
;
672 struct lbs_offset_value offval
;
673 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
674 char *buf
= (char *)addr
;
676 buf_size
= min(count
, len
- 1);
677 if (copy_from_user(buf
, userbuf
, buf_size
)) {
681 res
= sscanf(buf
, "%x %x", &offset
, &value
);
687 offval
.offset
= offset
;
688 offval
.value
= value
;
689 res
= lbs_prepare_and_send_command(priv
,
690 CMD_MAC_REG_ACCESS
, 1,
691 CMD_OPTION_WAITFORRSP
, 0, &offval
);
700 static ssize_t
lbs_rdbbp_read(struct file
*file
, char __user
*userbuf
,
701 size_t count
, loff_t
*ppos
)
703 struct lbs_private
*priv
= file
->private_data
;
704 struct lbs_offset_value offval
;
707 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
708 char *buf
= (char *)addr
;
710 offval
.offset
= priv
->bbp_offset
;
713 ret
= lbs_prepare_and_send_command(priv
,
714 CMD_BBP_REG_ACCESS
, 0,
715 CMD_OPTION_WAITFORRSP
, 0, &offval
);
717 pos
+= snprintf(buf
+pos
, len
-pos
, "BBP[0x%x] = 0x%08x\n",
718 priv
->bbp_offset
, priv
->offsetvalue
.value
);
720 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
726 static ssize_t
lbs_rdbbp_write(struct file
*file
,
727 const char __user
*userbuf
,
728 size_t count
, loff_t
*ppos
)
730 struct lbs_private
*priv
= file
->private_data
;
731 ssize_t res
, buf_size
;
732 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
733 char *buf
= (char *)addr
;
735 buf_size
= min(count
, len
- 1);
736 if (copy_from_user(buf
, userbuf
, buf_size
)) {
740 priv
->bbp_offset
= simple_strtoul((char *)buf
, NULL
, 16);
747 static ssize_t
lbs_wrbbp_write(struct file
*file
,
748 const char __user
*userbuf
,
749 size_t count
, loff_t
*ppos
)
752 struct lbs_private
*priv
= file
->private_data
;
753 ssize_t res
, buf_size
;
755 struct lbs_offset_value offval
;
756 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
757 char *buf
= (char *)addr
;
759 buf_size
= min(count
, len
- 1);
760 if (copy_from_user(buf
, userbuf
, buf_size
)) {
764 res
= sscanf(buf
, "%x %x", &offset
, &value
);
770 offval
.offset
= offset
;
771 offval
.value
= value
;
772 res
= lbs_prepare_and_send_command(priv
,
773 CMD_BBP_REG_ACCESS
, 1,
774 CMD_OPTION_WAITFORRSP
, 0, &offval
);
783 static ssize_t
lbs_rdrf_read(struct file
*file
, char __user
*userbuf
,
784 size_t count
, loff_t
*ppos
)
786 struct lbs_private
*priv
= file
->private_data
;
787 struct lbs_offset_value offval
;
790 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
791 char *buf
= (char *)addr
;
793 offval
.offset
= priv
->rf_offset
;
796 ret
= lbs_prepare_and_send_command(priv
,
797 CMD_RF_REG_ACCESS
, 0,
798 CMD_OPTION_WAITFORRSP
, 0, &offval
);
800 pos
+= snprintf(buf
+pos
, len
-pos
, "RF[0x%x] = 0x%08x\n",
801 priv
->rf_offset
, priv
->offsetvalue
.value
);
803 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
809 static ssize_t
lbs_rdrf_write(struct file
*file
,
810 const char __user
*userbuf
,
811 size_t count
, loff_t
*ppos
)
813 struct lbs_private
*priv
= file
->private_data
;
814 ssize_t res
, buf_size
;
815 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
816 char *buf
= (char *)addr
;
818 buf_size
= min(count
, len
- 1);
819 if (copy_from_user(buf
, userbuf
, buf_size
)) {
823 priv
->rf_offset
= simple_strtoul((char *)buf
, NULL
, 16);
830 static ssize_t
lbs_wrrf_write(struct file
*file
,
831 const char __user
*userbuf
,
832 size_t count
, loff_t
*ppos
)
835 struct lbs_private
*priv
= file
->private_data
;
836 ssize_t res
, buf_size
;
838 struct lbs_offset_value offval
;
839 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
840 char *buf
= (char *)addr
;
842 buf_size
= min(count
, len
- 1);
843 if (copy_from_user(buf
, userbuf
, buf_size
)) {
847 res
= sscanf(buf
, "%x %x", &offset
, &value
);
853 offval
.offset
= offset
;
854 offval
.value
= value
;
855 res
= lbs_prepare_and_send_command(priv
,
856 CMD_RF_REG_ACCESS
, 1,
857 CMD_OPTION_WAITFORRSP
, 0, &offval
);
866 #define FOPS(fread, fwrite) { \
867 .owner = THIS_MODULE, \
868 .open = open_file_generic, \
873 struct lbs_debugfs_files
{
876 struct file_operations fops
;
879 static struct lbs_debugfs_files debugfs_files
[] = {
880 { "info", 0444, FOPS(lbs_dev_info
, write_file_dummy
), },
881 { "getscantable", 0444, FOPS(lbs_getscantable
,
882 write_file_dummy
), },
883 { "sleepparams", 0644, FOPS(lbs_sleepparams_read
,
884 lbs_sleepparams_write
), },
885 { "extscan", 0600, FOPS(NULL
, lbs_extscan
), },
886 { "setuserscan", 0600, FOPS(NULL
, lbs_setuserscan
), },
889 static struct lbs_debugfs_files debugfs_events_files
[] = {
890 {"low_rssi", 0644, FOPS(lbs_lowrssi_read
,
891 lbs_lowrssi_write
), },
892 {"low_snr", 0644, FOPS(lbs_lowsnr_read
,
893 lbs_lowsnr_write
), },
894 {"failure_count", 0644, FOPS(lbs_failcount_read
,
895 lbs_failcount_write
), },
896 {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read
,
897 lbs_bcnmiss_write
), },
898 {"high_rssi", 0644, FOPS(lbs_highrssi_read
,
899 lbs_highrssi_write
), },
900 {"high_snr", 0644, FOPS(lbs_highsnr_read
,
901 lbs_highsnr_write
), },
904 static struct lbs_debugfs_files debugfs_regs_files
[] = {
905 {"rdmac", 0644, FOPS(lbs_rdmac_read
, lbs_rdmac_write
), },
906 {"wrmac", 0600, FOPS(NULL
, lbs_wrmac_write
), },
907 {"rdbbp", 0644, FOPS(lbs_rdbbp_read
, lbs_rdbbp_write
), },
908 {"wrbbp", 0600, FOPS(NULL
, lbs_wrbbp_write
), },
909 {"rdrf", 0644, FOPS(lbs_rdrf_read
, lbs_rdrf_write
), },
910 {"wrrf", 0600, FOPS(NULL
, lbs_wrrf_write
), },
913 void lbs_debugfs_init(void)
916 lbs_dir
= debugfs_create_dir("lbs_wireless", NULL
);
921 void lbs_debugfs_remove(void)
924 debugfs_remove(lbs_dir
);
928 void lbs_debugfs_init_one(struct lbs_private
*priv
, struct net_device
*dev
)
931 struct lbs_debugfs_files
*files
;
935 priv
->debugfs_dir
= debugfs_create_dir(dev
->name
, lbs_dir
);
936 if (!priv
->debugfs_dir
)
939 for (i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++) {
940 files
= &debugfs_files
[i
];
941 priv
->debugfs_files
[i
] = debugfs_create_file(files
->name
,
948 priv
->events_dir
= debugfs_create_dir("subscribed_events", priv
->debugfs_dir
);
949 if (!priv
->events_dir
)
952 for (i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++) {
953 files
= &debugfs_events_files
[i
];
954 priv
->debugfs_events_files
[i
] = debugfs_create_file(files
->name
,
961 priv
->regs_dir
= debugfs_create_dir("registers", priv
->debugfs_dir
);
965 for (i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++) {
966 files
= &debugfs_regs_files
[i
];
967 priv
->debugfs_regs_files
[i
] = debugfs_create_file(files
->name
,
975 lbs_debug_init(priv
, dev
);
981 void lbs_debugfs_remove_one(struct lbs_private
*priv
)
985 for(i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++)
986 debugfs_remove(priv
->debugfs_regs_files
[i
]);
988 debugfs_remove(priv
->regs_dir
);
990 for(i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++)
991 debugfs_remove(priv
->debugfs_events_files
[i
]);
993 debugfs_remove(priv
->events_dir
);
995 debugfs_remove(priv
->debugfs_debug
);
997 for(i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++)
998 debugfs_remove(priv
->debugfs_files
[i
]);
999 debugfs_remove(priv
->debugfs_dir
);
1008 #define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
1009 #define item_addr(n) (offsetof(struct lbs_private, n))
1018 /* To debug any member of struct lbs_private, simply add one line here.
1020 static struct debug_data items
[] = {
1021 {"intcounter", item_size(intcounter
), item_addr(intcounter
)},
1022 {"psmode", item_size(psmode
), item_addr(psmode
)},
1023 {"psstate", item_size(psstate
), item_addr(psstate
)},
1026 static int num_of_items
= ARRAY_SIZE(items
);
1029 * @brief proc read function
1031 * @param page pointer to buffer
1032 * @param s read data starting position
1034 * @param cnt counter
1035 * @param eof end of file flag
1036 * @param data data to output
1037 * @return number of output data
1039 static ssize_t
lbs_debugfs_read(struct file
*file
, char __user
*userbuf
,
1040 size_t count
, loff_t
*ppos
)
1047 struct debug_data
*d
;
1048 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
1049 char *buf
= (char *)addr
;
1053 d
= (struct debug_data
*)file
->private_data
;
1055 for (i
= 0; i
< num_of_items
; i
++) {
1057 val
= *((u8
*) d
[i
].addr
);
1058 else if (d
[i
].size
== 2)
1059 val
= *((u16
*) d
[i
].addr
);
1060 else if (d
[i
].size
== 4)
1061 val
= *((u32
*) d
[i
].addr
);
1062 else if (d
[i
].size
== 8)
1063 val
= *((u64
*) d
[i
].addr
);
1065 pos
+= sprintf(p
+ pos
, "%s=%d\n", d
[i
].name
, val
);
1068 res
= simple_read_from_buffer(userbuf
, count
, ppos
, p
, pos
);
1075 * @brief proc write function
1077 * @param f file pointer
1078 * @param buf pointer to data buffer
1079 * @param cnt data number to write
1080 * @param data data to write
1081 * @return number of data
1083 static ssize_t
lbs_debugfs_write(struct file
*f
, const char __user
*buf
,
1084 size_t cnt
, loff_t
*ppos
)
1092 struct debug_data
*d
= (struct debug_data
*)f
->private_data
;
1094 pdata
= kmalloc(cnt
, GFP_KERNEL
);
1098 if (copy_from_user(pdata
, buf
, cnt
)) {
1099 lbs_deb_debugfs("Copy from user failed\n");
1105 for (i
= 0; i
< num_of_items
; i
++) {
1107 p
= strstr(p0
, d
[i
].name
);
1110 p1
= strchr(p
, '\n');
1114 p2
= strchr(p
, '=');
1118 r
= simple_strtoul(p2
, NULL
, 0);
1120 *((u8
*) d
[i
].addr
) = (u8
) r
;
1121 else if (d
[i
].size
== 2)
1122 *((u16
*) d
[i
].addr
) = (u16
) r
;
1123 else if (d
[i
].size
== 4)
1124 *((u32
*) d
[i
].addr
) = (u32
) r
;
1125 else if (d
[i
].size
== 8)
1126 *((u64
*) d
[i
].addr
) = (u64
) r
;
1132 return (ssize_t
)cnt
;
1135 static struct file_operations lbs_debug_fops
= {
1136 .owner
= THIS_MODULE
,
1137 .open
= open_file_generic
,
1138 .write
= lbs_debugfs_write
,
1139 .read
= lbs_debugfs_read
,
1143 * @brief create debug proc file
1145 * @param priv pointer struct lbs_private
1146 * @param dev pointer net_device
1149 static void lbs_debug_init(struct lbs_private
*priv
, struct net_device
*dev
)
1153 if (!priv
->debugfs_dir
)
1156 for (i
= 0; i
< num_of_items
; i
++)
1157 items
[i
].addr
+= (size_t) priv
;
1159 priv
->debugfs_debug
= debugfs_create_file("debug", 0644,
1160 priv
->debugfs_dir
, &items
[0],