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>
15 static struct dentry
*lbs_dir
;
16 static char *szStates
[] = {
22 static void lbs_debug_init(struct lbs_private
*priv
, struct net_device
*dev
);
25 static int open_file_generic(struct inode
*inode
, struct file
*file
)
27 file
->private_data
= inode
->i_private
;
31 static ssize_t
write_file_dummy(struct file
*file
, const char __user
*buf
,
32 size_t count
, loff_t
*ppos
)
37 static const size_t len
= PAGE_SIZE
;
39 static ssize_t
lbs_dev_info(struct file
*file
, char __user
*userbuf
,
40 size_t count
, loff_t
*ppos
)
42 struct lbs_private
*priv
= file
->private_data
;
44 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
45 char *buf
= (char *)addr
;
48 pos
+= snprintf(buf
+pos
, len
-pos
, "state = %s\n",
49 szStates
[priv
->connect_status
]);
50 pos
+= snprintf(buf
+pos
, len
-pos
, "region_code = %02x\n",
51 (u32
) priv
->regioncode
);
53 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
60 static ssize_t
lbs_getscantable(struct file
*file
, char __user
*userbuf
,
61 size_t count
, loff_t
*ppos
)
63 struct lbs_private
*priv
= file
->private_data
;
65 int numscansdone
= 0, res
;
66 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
67 char *buf
= (char *)addr
;
69 struct bss_descriptor
* iter_bss
;
71 pos
+= snprintf(buf
+pos
, len
-pos
,
72 "# | ch | rssi | bssid | cap | Qual | SSID \n");
74 mutex_lock(&priv
->lock
);
75 list_for_each_entry (iter_bss
, &priv
->network_list
, list
) {
76 u16 ibss
= (iter_bss
->capability
& WLAN_CAPABILITY_IBSS
);
77 u16 privacy
= (iter_bss
->capability
& WLAN_CAPABILITY_PRIVACY
);
78 u16 spectrum_mgmt
= (iter_bss
->capability
& WLAN_CAPABILITY_SPECTRUM_MGMT
);
80 pos
+= snprintf(buf
+pos
, len
-pos
,
81 "%02u| %03d | %04ld | %s |",
82 numscansdone
, iter_bss
->channel
, iter_bss
->rssi
,
83 print_mac(mac
, iter_bss
->bssid
));
84 pos
+= snprintf(buf
+pos
, len
-pos
, " %04x-", iter_bss
->capability
);
85 pos
+= snprintf(buf
+pos
, len
-pos
, "%c%c%c |",
86 ibss
? 'A' : 'I', privacy
? 'P' : ' ',
87 spectrum_mgmt
? 'S' : ' ');
88 pos
+= snprintf(buf
+pos
, len
-pos
, " %04d |", SCAN_RSSI(iter_bss
->rssi
));
89 pos
+= snprintf(buf
+pos
, len
-pos
, " %s\n",
90 escape_essid(iter_bss
->ssid
, iter_bss
->ssid_len
));
94 mutex_unlock(&priv
->lock
);
96 res
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
102 static ssize_t
lbs_sleepparams_write(struct file
*file
,
103 const char __user
*user_buf
, size_t count
,
106 struct lbs_private
*priv
= file
->private_data
;
107 ssize_t buf_size
, ret
;
108 struct sleep_params sp
;
109 int p1
, p2
, p3
, p4
, p5
, p6
;
110 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
111 char *buf
= (char *)addr
;
113 buf_size
= min(count
, len
- 1);
114 if (copy_from_user(buf
, user_buf
, buf_size
)) {
118 ret
= sscanf(buf
, "%d %d %d %d %d %d", &p1
, &p2
, &p3
, &p4
, &p5
, &p6
);
125 sp
.sp_stabletime
= p3
;
126 sp
.sp_calcontrol
= p4
;
127 sp
.sp_extsleepclk
= p5
;
130 ret
= lbs_cmd_802_11_sleep_params(priv
, CMD_ACT_SET
, &sp
);
141 static ssize_t
lbs_sleepparams_read(struct file
*file
, char __user
*userbuf
,
142 size_t count
, loff_t
*ppos
)
144 struct lbs_private
*priv
= file
->private_data
;
147 struct sleep_params sp
;
148 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
149 char *buf
= (char *)addr
;
151 ret
= lbs_cmd_802_11_sleep_params(priv
, CMD_ACT_GET
, &sp
);
155 pos
+= snprintf(buf
, len
, "%d %d %d %d %d %d\n", sp
.sp_error
,
156 sp
.sp_offset
, sp
.sp_stabletime
,
157 sp
.sp_calcontrol
, sp
.sp_extsleepclk
,
160 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
167 static ssize_t
lbs_extscan(struct file
*file
, const char __user
*userbuf
,
168 size_t count
, loff_t
*ppos
)
170 struct lbs_private
*priv
= file
->private_data
;
171 ssize_t res
, buf_size
;
172 union iwreq_data wrqu
;
173 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
174 char *buf
= (char *)addr
;
176 buf_size
= min(count
, len
- 1);
177 if (copy_from_user(buf
, userbuf
, buf_size
)) {
182 lbs_send_specific_ssid_scan(priv
, buf
, strlen(buf
)-1, 0);
184 memset(&wrqu
, 0, sizeof(union iwreq_data
));
185 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
192 static void lbs_parse_bssid(char *buf
, size_t count
,
193 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
196 unsigned int mac
[ETH_ALEN
];
198 hold
= strstr(buf
, "bssid=");
202 sscanf(hold
, MAC_FMT
, mac
, mac
+1, mac
+2, mac
+3, mac
+4, mac
+5);
203 memcpy(scan_cfg
->bssid
, mac
, ETH_ALEN
);
206 static void lbs_parse_ssid(char *buf
, size_t count
,
207 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
212 hold
= strstr(buf
, "ssid=");
216 end
= strchr(hold
, ' ');
218 end
= buf
+ count
- 1;
220 size
= min((size_t)IW_ESSID_MAX_SIZE
, (size_t) (end
- hold
));
221 strncpy(scan_cfg
->ssid
, hold
, size
);
226 static int lbs_parse_clear(char *buf
, size_t count
, const char *tag
)
231 hold
= strstr(buf
, tag
);
235 sscanf(hold
, "%d", &val
);
243 static int lbs_parse_dur(char *buf
, size_t count
,
244 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
249 hold
= strstr(buf
, "dur=");
253 sscanf(hold
, "%d", &val
);
258 static void lbs_parse_type(char *buf
, size_t count
,
259 struct lbs_ioctl_user_scan_cfg
*scan_cfg
)
264 hold
= strstr(buf
, "type=");
268 sscanf(hold
, "%d", &val
);
271 if (val
< 1 || val
> 3)
274 scan_cfg
->bsstype
= val
;
279 static ssize_t
lbs_setuserscan(struct file
*file
,
280 const char __user
*userbuf
,
281 size_t count
, loff_t
*ppos
)
283 struct lbs_private
*priv
= file
->private_data
;
284 ssize_t res
, buf_size
;
285 struct lbs_ioctl_user_scan_cfg
*scan_cfg
;
286 union iwreq_data wrqu
;
288 char *buf
= (char *)get_zeroed_page(GFP_KERNEL
);
293 buf_size
= min(count
, len
- 1);
294 if (copy_from_user(buf
, userbuf
, buf_size
)) {
299 scan_cfg
= kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg
), GFP_KERNEL
);
306 scan_cfg
->bsstype
= LBS_SCAN_BSS_TYPE_ANY
;
308 dur
= lbs_parse_dur(buf
, count
, scan_cfg
);
309 lbs_parse_bssid(buf
, count
, scan_cfg
);
310 scan_cfg
->clear_bssid
= lbs_parse_clear(buf
, count
, "clear_bssid=");
311 lbs_parse_ssid(buf
, count
, scan_cfg
);
312 scan_cfg
->clear_ssid
= lbs_parse_clear(buf
, count
, "clear_ssid=");
313 lbs_parse_type(buf
, count
, scan_cfg
);
315 lbs_scan_networks(priv
, scan_cfg
, 1);
316 wait_event_interruptible(priv
->cmd_pending
,
317 priv
->surpriseremoved
|| !priv
->last_scanned_channel
);
319 if (priv
->surpriseremoved
)
322 memset(&wrqu
, 0x00, sizeof(union iwreq_data
));
323 wireless_send_event(priv
->dev
, SIOCGIWSCAN
, &wrqu
, NULL
);
328 free_page((unsigned long)buf
);
334 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
335 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
336 * firmware. Here's an example:
337 * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
338 * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
339 * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
341 * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
342 * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
343 * defined in mrvlietypes_thresholds
345 * This function searches in this TLV data chunk for a given TLV type
346 * and returns a pointer to the first data byte of the TLV, or to NULL
347 * if the TLV hasn't been found.
349 static void *lbs_tlv_find(uint16_t tlv_type
, const uint8_t *tlv
, uint16_t size
)
351 struct mrvlietypesheader
*tlv_h
;
356 tlv_h
= (struct mrvlietypesheader
*) tlv
;
359 if (tlv_h
->type
== cpu_to_le16(tlv_type
))
361 length
= le16_to_cpu(tlv_h
->len
) + sizeof(*tlv_h
);
369 static ssize_t
lbs_threshold_read(uint16_t tlv_type
, uint16_t event_mask
,
370 struct file
*file
, char __user
*userbuf
,
371 size_t count
, loff_t
*ppos
)
373 struct cmd_ds_802_11_subscribe_event
*subscribed
;
374 struct mrvlietypes_thresholds
*got
;
375 struct lbs_private
*priv
= file
->private_data
;
383 buf
= (char *)get_zeroed_page(GFP_KERNEL
);
387 subscribed
= kzalloc(sizeof(*subscribed
), GFP_KERNEL
);
393 subscribed
->hdr
.size
= cpu_to_le16(sizeof(*subscribed
));
394 subscribed
->action
= cpu_to_le16(CMD_ACT_GET
);
396 ret
= lbs_cmd_with_response(priv
, CMD_802_11_SUBSCRIBE_EVENT
, subscribed
);
400 got
= lbs_tlv_find(tlv_type
, subscribed
->tlv
, sizeof(subscribed
->tlv
));
404 events
= le16_to_cpu(subscribed
->events
);
406 pos
+= snprintf(buf
, len
, "%d %d %d\n", value
, freq
,
407 !!(events
& event_mask
));
410 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
416 free_page((unsigned long)buf
);
421 static ssize_t
lbs_threshold_write(uint16_t tlv_type
, uint16_t event_mask
,
423 const char __user
*userbuf
, size_t count
,
426 struct cmd_ds_802_11_subscribe_event
*events
;
427 struct mrvlietypes_thresholds
*tlv
;
428 struct lbs_private
*priv
= file
->private_data
;
430 int value
, freq
, new_mask
;
435 buf
= (char *)get_zeroed_page(GFP_KERNEL
);
439 buf_size
= min(count
, len
- 1);
440 if (copy_from_user(buf
, userbuf
, buf_size
)) {
444 ret
= sscanf(buf
, "%d %d %d", &value
, &freq
, &new_mask
);
449 events
= kzalloc(sizeof(*events
), GFP_KERNEL
);
455 events
->hdr
.size
= cpu_to_le16(sizeof(*events
));
456 events
->action
= cpu_to_le16(CMD_ACT_GET
);
458 ret
= lbs_cmd_with_response(priv
, CMD_802_11_SUBSCRIBE_EVENT
, events
);
462 curr_mask
= le16_to_cpu(events
->events
);
465 new_mask
= curr_mask
| event_mask
;
467 new_mask
= curr_mask
& ~event_mask
;
469 /* Now everything is set and we can send stuff down to the firmware */
471 tlv
= (void *)events
->tlv
;
473 events
->action
= cpu_to_le16(CMD_ACT_SET
);
474 events
->events
= cpu_to_le16(new_mask
);
475 tlv
->header
.type
= cpu_to_le16(tlv_type
);
476 tlv
->header
.len
= cpu_to_le16(sizeof(*tlv
) - sizeof(tlv
->header
));
478 if (tlv_type
!= TLV_TYPE_BCNMISS
)
481 /* The command header, the event mask, and the one TLV */
482 events
->hdr
.size
= cpu_to_le16(sizeof(events
->hdr
) + 2 + sizeof(*tlv
));
484 ret
= lbs_cmd_with_response(priv
, CMD_802_11_SUBSCRIBE_EVENT
, events
);
491 free_page((unsigned long)buf
);
496 static ssize_t
lbs_lowrssi_read(struct file
*file
, char __user
*userbuf
,
497 size_t count
, loff_t
*ppos
)
499 return lbs_threshold_read(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
500 file
, userbuf
, count
, ppos
);
504 static ssize_t
lbs_lowrssi_write(struct file
*file
, const char __user
*userbuf
,
505 size_t count
, loff_t
*ppos
)
507 return lbs_threshold_write(TLV_TYPE_RSSI_LOW
, CMD_SUBSCRIBE_RSSI_LOW
,
508 file
, userbuf
, count
, ppos
);
512 static ssize_t
lbs_lowsnr_read(struct file
*file
, char __user
*userbuf
,
513 size_t count
, loff_t
*ppos
)
515 return lbs_threshold_read(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
516 file
, userbuf
, count
, ppos
);
520 static ssize_t
lbs_lowsnr_write(struct file
*file
, const char __user
*userbuf
,
521 size_t count
, loff_t
*ppos
)
523 return lbs_threshold_write(TLV_TYPE_SNR_LOW
, CMD_SUBSCRIBE_SNR_LOW
,
524 file
, userbuf
, count
, ppos
);
528 static ssize_t
lbs_failcount_read(struct file
*file
, char __user
*userbuf
,
529 size_t count
, loff_t
*ppos
)
531 return lbs_threshold_read(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
532 file
, userbuf
, count
, ppos
);
536 static ssize_t
lbs_failcount_write(struct file
*file
, const char __user
*userbuf
,
537 size_t count
, loff_t
*ppos
)
539 return lbs_threshold_write(TLV_TYPE_FAILCOUNT
, CMD_SUBSCRIBE_FAILCOUNT
,
540 file
, userbuf
, count
, ppos
);
544 static ssize_t
lbs_highrssi_read(struct file
*file
, char __user
*userbuf
,
545 size_t count
, loff_t
*ppos
)
547 return lbs_threshold_read(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
548 file
, userbuf
, count
, ppos
);
552 static ssize_t
lbs_highrssi_write(struct file
*file
, const char __user
*userbuf
,
553 size_t count
, loff_t
*ppos
)
555 return lbs_threshold_write(TLV_TYPE_RSSI_HIGH
, CMD_SUBSCRIBE_RSSI_HIGH
,
556 file
, userbuf
, count
, ppos
);
560 static ssize_t
lbs_highsnr_read(struct file
*file
, char __user
*userbuf
,
561 size_t count
, loff_t
*ppos
)
563 return lbs_threshold_read(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
564 file
, userbuf
, count
, ppos
);
568 static ssize_t
lbs_highsnr_write(struct file
*file
, const char __user
*userbuf
,
569 size_t count
, loff_t
*ppos
)
571 return lbs_threshold_write(TLV_TYPE_SNR_HIGH
, CMD_SUBSCRIBE_SNR_HIGH
,
572 file
, userbuf
, count
, ppos
);
575 static ssize_t
lbs_bcnmiss_read(struct file
*file
, char __user
*userbuf
,
576 size_t count
, loff_t
*ppos
)
578 return lbs_threshold_read(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
579 file
, userbuf
, count
, ppos
);
583 static ssize_t
lbs_bcnmiss_write(struct file
*file
, const char __user
*userbuf
,
584 size_t count
, loff_t
*ppos
)
586 return lbs_threshold_write(TLV_TYPE_BCNMISS
, CMD_SUBSCRIBE_BCNMISS
,
587 file
, userbuf
, count
, ppos
);
592 static ssize_t
lbs_rdmac_read(struct file
*file
, char __user
*userbuf
,
593 size_t count
, loff_t
*ppos
)
595 struct lbs_private
*priv
= file
->private_data
;
596 struct lbs_offset_value offval
;
599 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
600 char *buf
= (char *)addr
;
602 offval
.offset
= priv
->mac_offset
;
605 ret
= lbs_prepare_and_send_command(priv
,
606 CMD_MAC_REG_ACCESS
, 0,
607 CMD_OPTION_WAITFORRSP
, 0, &offval
);
609 pos
+= snprintf(buf
+pos
, len
-pos
, "MAC[0x%x] = 0x%08x\n",
610 priv
->mac_offset
, priv
->offsetvalue
.value
);
612 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
617 static ssize_t
lbs_rdmac_write(struct file
*file
,
618 const char __user
*userbuf
,
619 size_t count
, loff_t
*ppos
)
621 struct lbs_private
*priv
= file
->private_data
;
622 ssize_t res
, buf_size
;
623 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
624 char *buf
= (char *)addr
;
626 buf_size
= min(count
, len
- 1);
627 if (copy_from_user(buf
, userbuf
, buf_size
)) {
631 priv
->mac_offset
= simple_strtoul((char *)buf
, NULL
, 16);
638 static ssize_t
lbs_wrmac_write(struct file
*file
,
639 const char __user
*userbuf
,
640 size_t count
, loff_t
*ppos
)
643 struct lbs_private
*priv
= file
->private_data
;
644 ssize_t res
, buf_size
;
646 struct lbs_offset_value offval
;
647 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
648 char *buf
= (char *)addr
;
650 buf_size
= min(count
, len
- 1);
651 if (copy_from_user(buf
, userbuf
, buf_size
)) {
655 res
= sscanf(buf
, "%x %x", &offset
, &value
);
661 offval
.offset
= offset
;
662 offval
.value
= value
;
663 res
= lbs_prepare_and_send_command(priv
,
664 CMD_MAC_REG_ACCESS
, 1,
665 CMD_OPTION_WAITFORRSP
, 0, &offval
);
674 static ssize_t
lbs_rdbbp_read(struct file
*file
, char __user
*userbuf
,
675 size_t count
, loff_t
*ppos
)
677 struct lbs_private
*priv
= file
->private_data
;
678 struct lbs_offset_value offval
;
681 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
682 char *buf
= (char *)addr
;
684 offval
.offset
= priv
->bbp_offset
;
687 ret
= lbs_prepare_and_send_command(priv
,
688 CMD_BBP_REG_ACCESS
, 0,
689 CMD_OPTION_WAITFORRSP
, 0, &offval
);
691 pos
+= snprintf(buf
+pos
, len
-pos
, "BBP[0x%x] = 0x%08x\n",
692 priv
->bbp_offset
, priv
->offsetvalue
.value
);
694 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
700 static ssize_t
lbs_rdbbp_write(struct file
*file
,
701 const char __user
*userbuf
,
702 size_t count
, loff_t
*ppos
)
704 struct lbs_private
*priv
= file
->private_data
;
705 ssize_t res
, buf_size
;
706 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
707 char *buf
= (char *)addr
;
709 buf_size
= min(count
, len
- 1);
710 if (copy_from_user(buf
, userbuf
, buf_size
)) {
714 priv
->bbp_offset
= simple_strtoul((char *)buf
, NULL
, 16);
721 static ssize_t
lbs_wrbbp_write(struct file
*file
,
722 const char __user
*userbuf
,
723 size_t count
, loff_t
*ppos
)
726 struct lbs_private
*priv
= file
->private_data
;
727 ssize_t res
, buf_size
;
729 struct lbs_offset_value offval
;
730 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
731 char *buf
= (char *)addr
;
733 buf_size
= min(count
, len
- 1);
734 if (copy_from_user(buf
, userbuf
, buf_size
)) {
738 res
= sscanf(buf
, "%x %x", &offset
, &value
);
744 offval
.offset
= offset
;
745 offval
.value
= value
;
746 res
= lbs_prepare_and_send_command(priv
,
747 CMD_BBP_REG_ACCESS
, 1,
748 CMD_OPTION_WAITFORRSP
, 0, &offval
);
757 static ssize_t
lbs_rdrf_read(struct file
*file
, char __user
*userbuf
,
758 size_t count
, loff_t
*ppos
)
760 struct lbs_private
*priv
= file
->private_data
;
761 struct lbs_offset_value offval
;
764 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
765 char *buf
= (char *)addr
;
767 offval
.offset
= priv
->rf_offset
;
770 ret
= lbs_prepare_and_send_command(priv
,
771 CMD_RF_REG_ACCESS
, 0,
772 CMD_OPTION_WAITFORRSP
, 0, &offval
);
774 pos
+= snprintf(buf
+pos
, len
-pos
, "RF[0x%x] = 0x%08x\n",
775 priv
->rf_offset
, priv
->offsetvalue
.value
);
777 ret
= simple_read_from_buffer(userbuf
, count
, ppos
, buf
, pos
);
783 static ssize_t
lbs_rdrf_write(struct file
*file
,
784 const char __user
*userbuf
,
785 size_t count
, loff_t
*ppos
)
787 struct lbs_private
*priv
= file
->private_data
;
788 ssize_t res
, buf_size
;
789 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
790 char *buf
= (char *)addr
;
792 buf_size
= min(count
, len
- 1);
793 if (copy_from_user(buf
, userbuf
, buf_size
)) {
797 priv
->rf_offset
= simple_strtoul((char *)buf
, NULL
, 16);
804 static ssize_t
lbs_wrrf_write(struct file
*file
,
805 const char __user
*userbuf
,
806 size_t count
, loff_t
*ppos
)
809 struct lbs_private
*priv
= file
->private_data
;
810 ssize_t res
, buf_size
;
812 struct lbs_offset_value offval
;
813 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
814 char *buf
= (char *)addr
;
816 buf_size
= min(count
, len
- 1);
817 if (copy_from_user(buf
, userbuf
, buf_size
)) {
821 res
= sscanf(buf
, "%x %x", &offset
, &value
);
827 offval
.offset
= offset
;
828 offval
.value
= value
;
829 res
= lbs_prepare_and_send_command(priv
,
830 CMD_RF_REG_ACCESS
, 1,
831 CMD_OPTION_WAITFORRSP
, 0, &offval
);
840 #define FOPS(fread, fwrite) { \
841 .owner = THIS_MODULE, \
842 .open = open_file_generic, \
847 struct lbs_debugfs_files
{
850 struct file_operations fops
;
853 static struct lbs_debugfs_files debugfs_files
[] = {
854 { "info", 0444, FOPS(lbs_dev_info
, write_file_dummy
), },
855 { "getscantable", 0444, FOPS(lbs_getscantable
,
856 write_file_dummy
), },
857 { "sleepparams", 0644, FOPS(lbs_sleepparams_read
,
858 lbs_sleepparams_write
), },
859 { "extscan", 0600, FOPS(NULL
, lbs_extscan
), },
860 { "setuserscan", 0600, FOPS(NULL
, lbs_setuserscan
), },
863 static struct lbs_debugfs_files debugfs_events_files
[] = {
864 {"low_rssi", 0644, FOPS(lbs_lowrssi_read
,
865 lbs_lowrssi_write
), },
866 {"low_snr", 0644, FOPS(lbs_lowsnr_read
,
867 lbs_lowsnr_write
), },
868 {"failure_count", 0644, FOPS(lbs_failcount_read
,
869 lbs_failcount_write
), },
870 {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read
,
871 lbs_bcnmiss_write
), },
872 {"high_rssi", 0644, FOPS(lbs_highrssi_read
,
873 lbs_highrssi_write
), },
874 {"high_snr", 0644, FOPS(lbs_highsnr_read
,
875 lbs_highsnr_write
), },
878 static struct lbs_debugfs_files debugfs_regs_files
[] = {
879 {"rdmac", 0644, FOPS(lbs_rdmac_read
, lbs_rdmac_write
), },
880 {"wrmac", 0600, FOPS(NULL
, lbs_wrmac_write
), },
881 {"rdbbp", 0644, FOPS(lbs_rdbbp_read
, lbs_rdbbp_write
), },
882 {"wrbbp", 0600, FOPS(NULL
, lbs_wrbbp_write
), },
883 {"rdrf", 0644, FOPS(lbs_rdrf_read
, lbs_rdrf_write
), },
884 {"wrrf", 0600, FOPS(NULL
, lbs_wrrf_write
), },
887 void lbs_debugfs_init(void)
890 lbs_dir
= debugfs_create_dir("lbs_wireless", NULL
);
895 void lbs_debugfs_remove(void)
898 debugfs_remove(lbs_dir
);
902 void lbs_debugfs_init_one(struct lbs_private
*priv
, struct net_device
*dev
)
905 struct lbs_debugfs_files
*files
;
909 priv
->debugfs_dir
= debugfs_create_dir(dev
->name
, lbs_dir
);
910 if (!priv
->debugfs_dir
)
913 for (i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++) {
914 files
= &debugfs_files
[i
];
915 priv
->debugfs_files
[i
] = debugfs_create_file(files
->name
,
922 priv
->events_dir
= debugfs_create_dir("subscribed_events", priv
->debugfs_dir
);
923 if (!priv
->events_dir
)
926 for (i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++) {
927 files
= &debugfs_events_files
[i
];
928 priv
->debugfs_events_files
[i
] = debugfs_create_file(files
->name
,
935 priv
->regs_dir
= debugfs_create_dir("registers", priv
->debugfs_dir
);
939 for (i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++) {
940 files
= &debugfs_regs_files
[i
];
941 priv
->debugfs_regs_files
[i
] = debugfs_create_file(files
->name
,
949 lbs_debug_init(priv
, dev
);
955 void lbs_debugfs_remove_one(struct lbs_private
*priv
)
959 for(i
=0; i
<ARRAY_SIZE(debugfs_regs_files
); i
++)
960 debugfs_remove(priv
->debugfs_regs_files
[i
]);
962 debugfs_remove(priv
->regs_dir
);
964 for(i
=0; i
<ARRAY_SIZE(debugfs_events_files
); i
++)
965 debugfs_remove(priv
->debugfs_events_files
[i
]);
967 debugfs_remove(priv
->events_dir
);
969 debugfs_remove(priv
->debugfs_debug
);
971 for(i
=0; i
<ARRAY_SIZE(debugfs_files
); i
++)
972 debugfs_remove(priv
->debugfs_files
[i
]);
973 debugfs_remove(priv
->debugfs_dir
);
982 #define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
983 #define item_addr(n) (offsetof(struct lbs_private, n))
992 /* To debug any member of struct lbs_private, simply add one line here.
994 static struct debug_data items
[] = {
995 {"intcounter", item_size(intcounter
), item_addr(intcounter
)},
996 {"psmode", item_size(psmode
), item_addr(psmode
)},
997 {"psstate", item_size(psstate
), item_addr(psstate
)},
1000 static int num_of_items
= ARRAY_SIZE(items
);
1003 * @brief proc read function
1005 * @param page pointer to buffer
1006 * @param s read data starting position
1008 * @param cnt counter
1009 * @param eof end of file flag
1010 * @param data data to output
1011 * @return number of output data
1013 static ssize_t
lbs_debugfs_read(struct file
*file
, char __user
*userbuf
,
1014 size_t count
, loff_t
*ppos
)
1021 struct debug_data
*d
;
1022 unsigned long addr
= get_zeroed_page(GFP_KERNEL
);
1023 char *buf
= (char *)addr
;
1027 d
= (struct debug_data
*)file
->private_data
;
1029 for (i
= 0; i
< num_of_items
; i
++) {
1031 val
= *((u8
*) d
[i
].addr
);
1032 else if (d
[i
].size
== 2)
1033 val
= *((u16
*) d
[i
].addr
);
1034 else if (d
[i
].size
== 4)
1035 val
= *((u32
*) d
[i
].addr
);
1036 else if (d
[i
].size
== 8)
1037 val
= *((u64
*) d
[i
].addr
);
1039 pos
+= sprintf(p
+ pos
, "%s=%d\n", d
[i
].name
, val
);
1042 res
= simple_read_from_buffer(userbuf
, count
, ppos
, p
, pos
);
1049 * @brief proc write function
1051 * @param f file pointer
1052 * @param buf pointer to data buffer
1053 * @param cnt data number to write
1054 * @param data data to write
1055 * @return number of data
1057 static ssize_t
lbs_debugfs_write(struct file
*f
, const char __user
*buf
,
1058 size_t cnt
, loff_t
*ppos
)
1066 struct debug_data
*d
= (struct debug_data
*)f
->private_data
;
1068 pdata
= kmalloc(cnt
, GFP_KERNEL
);
1072 if (copy_from_user(pdata
, buf
, cnt
)) {
1073 lbs_deb_debugfs("Copy from user failed\n");
1079 for (i
= 0; i
< num_of_items
; i
++) {
1081 p
= strstr(p0
, d
[i
].name
);
1084 p1
= strchr(p
, '\n');
1088 p2
= strchr(p
, '=');
1092 r
= simple_strtoul(p2
, NULL
, 0);
1094 *((u8
*) d
[i
].addr
) = (u8
) r
;
1095 else if (d
[i
].size
== 2)
1096 *((u16
*) d
[i
].addr
) = (u16
) r
;
1097 else if (d
[i
].size
== 4)
1098 *((u32
*) d
[i
].addr
) = (u32
) r
;
1099 else if (d
[i
].size
== 8)
1100 *((u64
*) d
[i
].addr
) = (u64
) r
;
1106 return (ssize_t
)cnt
;
1109 static struct file_operations lbs_debug_fops
= {
1110 .owner
= THIS_MODULE
,
1111 .open
= open_file_generic
,
1112 .write
= lbs_debugfs_write
,
1113 .read
= lbs_debugfs_read
,
1117 * @brief create debug proc file
1119 * @param priv pointer struct lbs_private
1120 * @param dev pointer net_device
1123 static void lbs_debug_init(struct lbs_private
*priv
, struct net_device
*dev
)
1127 if (!priv
->debugfs_dir
)
1130 for (i
= 0; i
< num_of_items
; i
++)
1131 items
[i
].addr
+= (size_t) priv
;
1133 priv
->debugfs_debug
= debugfs_create_file("debug", 0644,
1134 priv
->debugfs_dir
, &items
[0],