]> Pileus Git - ~andy/linux/blob - drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
staging: ft1000: rename struct ft1000_device to ft1000_usb
[~andy/linux] / drivers / staging / ft1000 / ft1000-usb / ft1000_proc.c
1 /*
2  * ft1000_proc.c - ft1000 proc interface
3  *
4  * Copyright    (C) 2009-2010 Quintec
5  *              (C) 2010 Open-nandra
6  *      <marek.belisko@open-nandra.com>
7  *
8  * This file is subject to the terms and conditions of the GNU General
9  * Public License. See the file "COPYING" in the main directory of this
10  * archive for more details.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/proc_fs.h>
25 #include <linux/netdevice.h>
26
27
28 #include "ft1000_usb.h"
29
30 #define FT1000_PROC_DIR "ft1000"
31
32
33 #define PUTM_TO_PAGE(len,page,args...) \
34         len += snprintf(page+len, PAGE_SIZE - len, args)
35
36 #define PUTX_TO_PAGE(len,page,message,size,var) \
37         len += snprintf(page+len, PAGE_SIZE - len, message); \
38         for (i = 0; i < (size - 1); i++) {\
39                 len += snprintf(page+len, PAGE_SIZE - len, "%02x:", var[i]); \
40         } \
41         len += snprintf(page+len, PAGE_SIZE - len, "%02x\n", var[i])
42
43 #define PUTD_TO_PAGE(len,page,message,size,var) \
44         len += snprintf(page+len, PAGE_SIZE - len, message); \
45         for (i = 0; i < (size - 1); i++) {\
46                 len += snprintf(page+len, PAGE_SIZE - len, "%d.", var[i]); \
47         } \
48         len += snprintf(page+len, PAGE_SIZE - len, "%d\n", var[i])
49
50
51 #define FTNET_PROC init_net.proc_net
52
53
54 int ft1000_read_dpram16 (struct ft1000_usb *ft1000dev, u16 indx,
55                          u8 *buffer, u8 highlow);
56
57
58 static int
59 ft1000ReadProc(char *page, char **start, off_t off, int count, int *eof,
60                 void *data)
61 {
62         struct net_device *dev;
63         int len;
64         int i;
65         unsigned short ledStat;
66         unsigned short conStat;
67
68         struct ft1000_info *info;
69
70         char *status[] = { 
71                 "Idle (Disconnect)", 
72                 "Searching",
73                 "Active (Connected)",
74                 "Waiting for L2",
75                 "Sleep",
76                 "No Coverage",
77                 "",
78                 "",
79         };
80
81         char *signal[] = { "", "*", "**", "***", "****" };
82         int strength;
83         int quality;
84         struct timeval tv;
85         time_t delta;
86
87         dev = (struct net_device *) data;
88         info = netdev_priv(dev);
89
90         if (off > 0) {
91                 *eof = 1;
92                 return 0;
93         }
94
95
96         if (info->ProgConStat != 0xFF) {
97                 ft1000_read_dpram16(info->priv, FT1000_MAG_DSP_LED,
98                            (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
99                 info->LedStat = ntohs(ledStat);
100
101                 ft1000_read_dpram16(info->priv, FT1000_MAG_DSP_CON_STATE,
102                         (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
103                 info->ConStat = ntohs(conStat);
104                 do_gettimeofday(&tv);
105                 delta = (tv.tv_sec - info->ConTm);
106         } else {
107                 info->ConStat = 0xf;
108                 delta = 0;
109         }
110
111         i = (info->LedStat) & 0xf;
112         switch (i) {
113         case 0x1:
114                 strength = 1;
115                 break;
116         case 0x3:
117                 strength = 2;
118                 break;
119         case 0x7:
120                 strength = 3;
121                 break;
122         case 0xf:
123                 strength = 4;
124                 break;
125         default:
126                 strength = 0;
127         }
128
129         i = (info->LedStat >> 8) & 0xf;
130         switch (i) {
131         case 0x1:
132                 quality = 1;
133                 break;
134         case 0x3:
135                 quality = 2;
136                 break;
137         case 0x7:
138                 quality = 3;
139                 break;
140         case 0xf:
141                 quality = 4;
142                 break;
143         default:
144                 quality = 0;
145         }
146
147         len = 0;
148         PUTM_TO_PAGE(len, page, "Connection Time: %02ld:%02ld:%02ld\n",
149                 ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
150         PUTM_TO_PAGE(len, page, "Connection Time[s]: %ld\n", delta);
151         PUTM_TO_PAGE(len, page, "Asic ID: %s\n",
152         (info->AsicID) ==
153         ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
154         PUTX_TO_PAGE(len, page, "SKU: ", SKUSZ, info->Sku);
155         PUTX_TO_PAGE(len, page, "EUI64: ", EUISZ, info->eui64);
156         PUTD_TO_PAGE(len, page, "DSP version number: ", DSPVERSZ, info->DspVer);
157         PUTX_TO_PAGE(len, page, "Hardware Serial Number: ", HWSERNUMSZ,
158                 info->HwSerNum);
159         PUTX_TO_PAGE(len, page, "Caliberation Version: ", CALVERSZ,
160                 info->RfCalVer);
161         PUTD_TO_PAGE(len, page, "Caliberation Date: ", CALDATESZ,
162                 info->RfCalDate);
163         PUTM_TO_PAGE(len, page, "Media State: %s\n",
164                 (info->mediastate) ? "link" : "no link");
165         PUTM_TO_PAGE(len, page, "Connection Status: %s\n",
166                 status[((info->ConStat) & 0x7)]);
167         PUTM_TO_PAGE(len, page, "RX packets: %ld\n", info->stats.rx_packets);
168         PUTM_TO_PAGE(len, page, "TX packets: %ld\n", info->stats.tx_packets);
169         PUTM_TO_PAGE(len, page, "RX bytes: %ld\n", info->stats.rx_bytes);
170         PUTM_TO_PAGE(len, page, "TX bytes: %ld\n", info->stats.tx_bytes);
171         PUTM_TO_PAGE(len, page, "Signal Strength: %s\n", signal[strength]);
172         PUTM_TO_PAGE(len, page, "Signal Quality: %s\n", signal[quality]);
173
174         return len;
175 }
176
177 static int
178 ft1000NotifyProc(struct notifier_block *this, unsigned long event, void *ptr)
179 {
180         struct net_device *dev = ptr;
181         struct ft1000_info *info;
182         struct proc_dir_entry *ft1000_proc_file;
183
184         info = netdev_priv(dev);
185
186         switch (event) {
187         case NETDEV_CHANGENAME:
188                 remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
189                 ft1000_proc_file = create_proc_read_entry(dev->name, 0644,
190                                         info->ft1000_proc_dir,
191                                         ft1000ReadProc, dev);
192                 snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
193                 break;
194         }
195
196         return NOTIFY_DONE;
197 }
198
199 static struct notifier_block ft1000_netdev_notifier = {
200         .notifier_call = ft1000NotifyProc,
201 };
202
203
204 int ft1000_init_proc(struct net_device *dev)
205 {
206         struct ft1000_info *info;
207         struct proc_dir_entry *ft1000_proc_file;
208         int ret = -EINVAL;
209
210         info = netdev_priv(dev);
211
212         info->ft1000_proc_dir = proc_mkdir(FT1000_PROC_DIR, FTNET_PROC);
213         if (info->ft1000_proc_dir == NULL) {
214                 printk(KERN_WARNING "Unable to create %s dir.\n",
215                         FT1000_PROC_DIR);
216                 goto fail;
217         }
218
219         ft1000_proc_file =
220                 create_proc_read_entry(dev->name, 0644,
221                         info->ft1000_proc_dir, ft1000ReadProc, dev);
222
223         if (ft1000_proc_file == NULL) {
224                 printk(KERN_WARNING "Unable to create /proc entry.\n");
225                 goto fail_entry;
226         }
227
228         snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
229
230         ret = register_netdevice_notifier(&ft1000_netdev_notifier);
231         if (ret)
232                 goto fail_notif;
233
234         return 0;
235
236 fail_notif:
237         remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
238 fail_entry:
239         remove_proc_entry(FT1000_PROC_DIR, FTNET_PROC);
240 fail:
241         return ret;
242 }
243
244 void ft1000_cleanup_proc(struct ft1000_info *info)
245 {
246         remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
247         remove_proc_entry(FT1000_PROC_DIR, FTNET_PROC);
248         unregister_netdevice_notifier(&ft1000_netdev_notifier);
249 }