]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/net/wireless/wl12xx/wl1271_cmd.c
Merge branch 'sched-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6.git] / drivers / net / wireless / wl12xx / wl1271_cmd.c
1 /*
2  * This file is part of wl1271
3  *
4  * Copyright (C) 2009 Nokia Corporation
5  *
6  * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * 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., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/crc7.h>
27 #include <linux/spi/spi.h>
28 #include <linux/etherdevice.h>
29
30 #include "wl1271.h"
31 #include "wl1271_reg.h"
32 #include "wl1271_spi.h"
33 #include "wl1271_acx.h"
34 #include "wl12xx_80211.h"
35 #include "wl1271_cmd.h"
36
37 /*
38  * send command to firmware
39  *
40  * @wl: wl struct
41  * @id: command id
42  * @buf: buffer containing the command, must work with dma
43  * @len: length of the buffer
44  */
45 int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
46 {
47         struct wl1271_cmd_header *cmd;
48         unsigned long timeout;
49         u32 intr;
50         int ret = 0;
51
52         cmd = buf;
53         cmd->id = id;
54         cmd->status = 0;
55
56         WARN_ON(len % 4 != 0);
57
58         wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len);
59
60         wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
61
62         timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
63
64         intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
65         while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
66                 if (time_after(jiffies, timeout)) {
67                         wl1271_error("command complete timeout");
68                         ret = -ETIMEDOUT;
69                         goto out;
70                 }
71
72                 msleep(1);
73
74                 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
75         }
76
77         wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
78                            WL1271_ACX_INTR_CMD_COMPLETE);
79
80 out:
81         return ret;
82 }
83
84 int wl1271_cmd_cal_channel_tune(struct wl1271 *wl)
85 {
86         struct wl1271_cmd_cal_channel_tune *cmd;
87         int ret = 0;
88
89         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
90         if (!cmd)
91                 return -ENOMEM;
92
93         cmd->test.id = TEST_CMD_CHANNEL_TUNE;
94
95         cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4;
96         /* set up any channel, 7 is in the middle of the range */
97         cmd->channel = 7;
98
99         ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
100         if (ret < 0)
101                 wl1271_warning("TEST_CMD_CHANNEL_TUNE failed");
102
103         kfree(cmd);
104         return ret;
105 }
106
107 int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl)
108 {
109         struct wl1271_cmd_cal_update_ref_point *cmd;
110         int ret = 0;
111
112         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
113         if (!cmd)
114                 return -ENOMEM;
115
116         cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT;
117
118         /* FIXME: still waiting for the correct values */
119         cmd->ref_power    = 0;
120         cmd->ref_detector = 0;
121
122         cmd->sub_band     = WL1271_PD_REFERENCE_POINT_BAND_B_G;
123
124         ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
125         if (ret < 0)
126                 wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed");
127
128         kfree(cmd);
129         return ret;
130 }
131
132 int wl1271_cmd_cal_p2g(struct wl1271 *wl)
133 {
134         struct wl1271_cmd_cal_p2g *cmd;
135         int ret = 0;
136
137         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
138         if (!cmd)
139                 return -ENOMEM;
140
141         cmd->test.id = TEST_CMD_P2G_CAL;
142
143         cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G;
144
145         ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
146         if (ret < 0)
147                 wl1271_warning("TEST_CMD_P2G_CAL failed");
148
149         kfree(cmd);
150         return ret;
151 }
152
153 int wl1271_cmd_cal(struct wl1271 *wl)
154 {
155         /*
156          * FIXME: we must make sure that we're not sleeping when calibration
157          * is done
158          */
159         int ret;
160
161         wl1271_notice("performing tx calibration");
162
163         ret = wl1271_cmd_cal_channel_tune(wl);
164         if (ret < 0)
165                 return ret;
166
167         ret = wl1271_cmd_cal_update_ref_point(wl);
168         if (ret < 0)
169                 return ret;
170
171         ret = wl1271_cmd_cal_p2g(wl);
172         if (ret < 0)
173                 return ret;
174
175         return ret;
176 }
177
178 int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
179                     u16 beacon_interval, u8 wait)
180 {
181         static bool do_cal = true;
182         unsigned long timeout;
183         struct wl1271_cmd_join *join;
184         int ret, i;
185         u8 *bssid;
186
187         /* FIXME: remove when we get calibration from the factory */
188         if (do_cal) {
189                 ret = wl1271_cmd_cal(wl);
190                 if (ret < 0)
191                         wl1271_warning("couldn't calibrate");
192                 else
193                         do_cal = false;
194         }
195
196
197         join = kzalloc(sizeof(*join), GFP_KERNEL);
198         if (!join) {
199                 ret = -ENOMEM;
200                 goto out;
201         }
202
203         wl1271_debug(DEBUG_CMD, "cmd join");
204
205         /* Reverse order BSSID */
206         bssid = (u8 *) &join->bssid_lsb;
207         for (i = 0; i < ETH_ALEN; i++)
208                 bssid[i] = wl->bssid[ETH_ALEN - i - 1];
209
210         join->rx_config_options = wl->rx_config;
211         join->rx_filter_options = wl->rx_filter;
212
213         join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
214                 RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
215
216         join->beacon_interval = beacon_interval;
217         join->dtim_interval = dtim_interval;
218         join->bss_type = bss_type;
219         join->channel = wl->channel;
220         join->ssid_len = wl->ssid_len;
221         memcpy(join->ssid, wl->ssid, wl->ssid_len);
222         join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH;
223
224         /* increment the session counter */
225         wl->session_counter++;
226         if (wl->session_counter >= SESSION_COUNTER_MAX)
227                 wl->session_counter = 0;
228
229         join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
230
231
232         ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
233         if (ret < 0) {
234                 wl1271_error("failed to initiate cmd join");
235                 goto out_free;
236         }
237
238         timeout = msecs_to_jiffies(JOIN_TIMEOUT);
239
240         /*
241          * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
242          * simplify locking we just sleep instead, for now
243          */
244         if (wait)
245                 msleep(10);
246
247 out_free:
248         kfree(join);
249
250 out:
251         return ret;
252 }
253
254 /**
255  * send test command to firmware
256  *
257  * @wl: wl struct
258  * @buf: buffer containing the command, with all headers, must work with dma
259  * @len: length of the buffer
260  * @answer: is answer needed
261  */
262 int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
263 {
264         int ret;
265
266         wl1271_debug(DEBUG_CMD, "cmd test");
267
268         ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);
269
270         if (ret < 0) {
271                 wl1271_warning("TEST command failed");
272                 return ret;
273         }
274
275         if (answer) {
276                 struct wl1271_command *cmd_answer;
277
278                 /*
279                  * The test command got in, we can read the answer.
280                  * The answer would be a wl1271_command, where the
281                  * parameter array contains the actual answer.
282                  */
283                 wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
284
285                 cmd_answer = buf;
286
287                 if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
288                         wl1271_error("TEST command answer error: %d",
289                                      cmd_answer->header.status);
290         }
291
292         return 0;
293 }
294
295 /**
296  * read acx from firmware
297  *
298  * @wl: wl struct
299  * @id: acx id
300  * @buf: buffer for the response, including all headers, must work with dma
301  * @len: lenght of buf
302  */
303 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
304 {
305         struct acx_header *acx = buf;
306         int ret;
307
308         wl1271_debug(DEBUG_CMD, "cmd interrogate");
309
310         acx->id = id;
311
312         /* payload length, does not include any headers */
313         acx->len = len - sizeof(*acx);
314
315         ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
316         if (ret < 0) {
317                 wl1271_error("INTERROGATE command failed");
318                 goto out;
319         }
320
321         /* the interrogate command got in, we can read the answer */
322         wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len);
323
324         acx = buf;
325         if (acx->cmd.status != CMD_STATUS_SUCCESS)
326                 wl1271_error("INTERROGATE command error: %d",
327                              acx->cmd.status);
328
329 out:
330         return ret;
331 }
332
333 /**
334  * write acx value to firmware
335  *
336  * @wl: wl struct
337  * @id: acx id
338  * @buf: buffer containing acx, including all headers, must work with dma
339  * @len: length of buf
340  */
341 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
342 {
343         struct acx_header *acx = buf;
344         int ret;
345
346         wl1271_debug(DEBUG_CMD, "cmd configure");
347
348         acx->id = id;
349
350         /* payload length, does not include any headers */
351         acx->len = len - sizeof(*acx);
352
353         ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len);
354         if (ret < 0) {
355                 wl1271_warning("CONFIGURE command NOK");
356                 return ret;
357         }
358
359         return 0;
360 }
361
362 int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
363 {
364         struct cmd_enabledisable_path *cmd;
365         int ret;
366         u16 cmd_rx, cmd_tx;
367
368         wl1271_debug(DEBUG_CMD, "cmd data path");
369
370         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
371         if (!cmd) {
372                 ret = -ENOMEM;
373                 goto out;
374         }
375
376         cmd->channel = channel;
377
378         if (enable) {
379                 cmd_rx = CMD_ENABLE_RX;
380                 cmd_tx = CMD_ENABLE_TX;
381         } else {
382                 cmd_rx = CMD_DISABLE_RX;
383                 cmd_tx = CMD_DISABLE_TX;
384         }
385
386         ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
387         if (ret < 0) {
388                 wl1271_error("rx %s cmd for channel %d failed",
389                              enable ? "start" : "stop", channel);
390                 goto out;
391         }
392
393         wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
394                      enable ? "start" : "stop", channel);
395
396         ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
397         if (ret < 0) {
398                 wl1271_error("tx %s cmd for channel %d failed",
399                              enable ? "start" : "stop", channel);
400                 return ret;
401         }
402
403         wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
404                      enable ? "start" : "stop", channel);
405
406 out:
407         kfree(cmd);
408         return ret;
409 }
410
411 int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
412 {
413         struct wl1271_cmd_ps_params *ps_params = NULL;
414         int ret = 0;
415
416         /* FIXME: this should be in ps.c */
417         ret = wl1271_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP,
418                                             wl->listen_int);
419         if (ret < 0) {
420                 wl1271_error("couldn't set wake up conditions");
421                 goto out;
422         }
423
424         wl1271_debug(DEBUG_CMD, "cmd set ps mode");
425
426         ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
427         if (!ps_params) {
428                 ret = -ENOMEM;
429                 goto out;
430         }
431
432         ps_params->ps_mode = ps_mode;
433         ps_params->send_null_data = 1;
434         ps_params->retries = 5;
435         ps_params->hang_over_period = 128;
436         ps_params->null_data_rate = 1; /* 1 Mbps */
437
438         ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
439                               sizeof(*ps_params));
440         if (ret < 0) {
441                 wl1271_error("cmd set_ps_mode failed");
442                 goto out;
443         }
444
445 out:
446         kfree(ps_params);
447         return ret;
448 }
449
450 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
451                            size_t len)
452 {
453         struct cmd_read_write_memory *cmd;
454         int ret = 0;
455
456         wl1271_debug(DEBUG_CMD, "cmd read memory");
457
458         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
459         if (!cmd) {
460                 ret = -ENOMEM;
461                 goto out;
462         }
463
464         WARN_ON(len > MAX_READ_SIZE);
465         len = min_t(size_t, len, MAX_READ_SIZE);
466
467         cmd->addr = addr;
468         cmd->size = len;
469
470         ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
471         if (ret < 0) {
472                 wl1271_error("read memory command failed: %d", ret);
473                 goto out;
474         }
475
476         /* the read command got in, we can now read the answer */
477         wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
478
479         if (cmd->header.status != CMD_STATUS_SUCCESS)
480                 wl1271_error("error in read command result: %d",
481                              cmd->header.status);
482
483         memcpy(answer, cmd->value, len);
484
485 out:
486         kfree(cmd);
487         return ret;
488 }
489
490 int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
491                     u8 active_scan, u8 high_prio, u8 num_channels,
492                     u8 probe_requests)
493 {
494
495         struct wl1271_cmd_trigger_scan_to *trigger = NULL;
496         struct wl1271_cmd_scan *params = NULL;
497         int i, ret;
498         u16 scan_options = 0;
499
500         if (wl->scanning)
501                 return -EINVAL;
502
503         params = kzalloc(sizeof(*params), GFP_KERNEL);
504         if (!params)
505                 return -ENOMEM;
506
507         params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
508         params->params.rx_filter_options =
509                 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
510
511         if (!active_scan)
512                 scan_options |= WL1271_SCAN_OPT_PASSIVE;
513         if (high_prio)
514                 scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
515         params->params.scan_options = scan_options;
516
517         params->params.num_channels = num_channels;
518         params->params.num_probe_requests = probe_requests;
519         params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS);
520         params->params.tid_trigger = 0;
521         params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
522
523         for (i = 0; i < num_channels; i++) {
524                 params->channels[i].min_duration =
525                         cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
526                 params->channels[i].max_duration =
527                         cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
528                 memset(&params->channels[i].bssid_lsb, 0xff, 4);
529                 memset(&params->channels[i].bssid_msb, 0xff, 2);
530                 params->channels[i].early_termination = 0;
531                 params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
532                 params->channels[i].channel = i + 1;
533         }
534
535         if (len && ssid) {
536                 params->params.ssid_len = len;
537                 memcpy(params->params.ssid, ssid, len);
538         }
539
540         ret = wl1271_cmd_build_probe_req(wl, ssid, len);
541         if (ret < 0) {
542                 wl1271_error("PROBE request template failed");
543                 goto out;
544         }
545
546         trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
547         if (!trigger) {
548                 ret = -ENOMEM;
549                 goto out;
550         }
551
552         /* disable the timeout */
553         trigger->timeout = 0;
554
555         ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
556                               sizeof(*trigger));
557         if (ret < 0) {
558                 wl1271_error("trigger scan to failed for hw scan");
559                 goto out;
560         }
561
562         wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
563
564         wl->scanning = true;
565
566         ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
567         if (ret < 0) {
568                 wl1271_error("SCAN failed");
569                 goto out;
570         }
571
572         wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
573
574         if (params->header.status != CMD_STATUS_SUCCESS) {
575                 wl1271_error("Scan command error: %d",
576                              params->header.status);
577                 wl->scanning = false;
578                 ret = -EIO;
579                 goto out;
580         }
581
582 out:
583         kfree(params);
584         return ret;
585 }
586
587 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
588                             void *buf, size_t buf_len)
589 {
590         struct wl1271_cmd_template_set *cmd;
591         int ret = 0;
592
593         wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id);
594
595         WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE);
596         buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE);
597
598         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
599         if (!cmd) {
600                 ret = -ENOMEM;
601                 goto out;
602         }
603
604         cmd->len = cpu_to_le16(buf_len);
605         cmd->template_type = template_id;
606         cmd->enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
607         cmd->short_retry_limit = ACX_RATE_RETRY_LIMIT;
608         cmd->long_retry_limit = ACX_RATE_RETRY_LIMIT;
609
610         if (buf)
611                 memcpy(cmd->template_data, buf, buf_len);
612
613         ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd));
614         if (ret < 0) {
615                 wl1271_warning("cmd set_template failed: %d", ret);
616                 goto out_free;
617         }
618
619 out_free:
620         kfree(cmd);
621
622 out:
623         return ret;
624 }
625
626 static int wl1271_build_basic_rates(char *rates)
627 {
628         u8 index = 0;
629
630         rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
631         rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
632         rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
633         rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
634
635         return index;
636 }
637
638 static int wl1271_build_extended_rates(char *rates)
639 {
640         u8 index = 0;
641
642         rates[index++] = IEEE80211_OFDM_RATE_6MB;
643         rates[index++] = IEEE80211_OFDM_RATE_9MB;
644         rates[index++] = IEEE80211_OFDM_RATE_12MB;
645         rates[index++] = IEEE80211_OFDM_RATE_18MB;
646         rates[index++] = IEEE80211_OFDM_RATE_24MB;
647         rates[index++] = IEEE80211_OFDM_RATE_36MB;
648         rates[index++] = IEEE80211_OFDM_RATE_48MB;
649         rates[index++] = IEEE80211_OFDM_RATE_54MB;
650
651         return index;
652 }
653
654 int wl1271_cmd_build_null_data(struct wl1271 *wl)
655 {
656         struct wl12xx_null_data_template template;
657
658         if (!is_zero_ether_addr(wl->bssid)) {
659                 memcpy(template.header.da, wl->bssid, ETH_ALEN);
660                 memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
661         } else {
662                 memset(template.header.da, 0xff, ETH_ALEN);
663                 memset(template.header.bssid, 0xff, ETH_ALEN);
664         }
665
666         memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
667         template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
668                                                 IEEE80211_STYPE_NULLFUNC);
669
670         return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template,
671                                        sizeof(template));
672
673 }
674
675 int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
676 {
677         struct wl12xx_ps_poll_template template;
678
679         memcpy(template.bssid, wl->bssid, ETH_ALEN);
680         memcpy(template.ta, wl->mac_addr, ETH_ALEN);
681         template.aid = aid;
682         template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
683
684         return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template,
685                                        sizeof(template));
686
687 }
688
689 int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len)
690 {
691         struct wl12xx_probe_req_template template;
692         struct wl12xx_ie_rates *rates;
693         char *ptr;
694         u16 size;
695
696         ptr = (char *)&template;
697         size = sizeof(struct ieee80211_header);
698
699         memset(template.header.da, 0xff, ETH_ALEN);
700         memset(template.header.bssid, 0xff, ETH_ALEN);
701         memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
702         template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
703
704         /* IEs */
705         /* SSID */
706         template.ssid.header.id = WLAN_EID_SSID;
707         template.ssid.header.len = ssid_len;
708         if (ssid_len && ssid)
709                 memcpy(template.ssid.ssid, ssid, ssid_len);
710         size += sizeof(struct wl12xx_ie_header) + ssid_len;
711         ptr += size;
712
713         /* Basic Rates */
714         rates = (struct wl12xx_ie_rates *)ptr;
715         rates->header.id = WLAN_EID_SUPP_RATES;
716         rates->header.len = wl1271_build_basic_rates(rates->rates);
717         size += sizeof(struct wl12xx_ie_header) + rates->header.len;
718         ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
719
720         /* Extended rates */
721         rates = (struct wl12xx_ie_rates *)ptr;
722         rates->header.id = WLAN_EID_EXT_SUPP_RATES;
723         rates->header.len = wl1271_build_extended_rates(rates->rates);
724         size += sizeof(struct wl12xx_ie_header) + rates->header.len;
725
726         wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
727
728         return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
729                                        &template, size);
730 }
731
732 int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
733 {
734         struct wl1271_cmd_set_keys *cmd;
735         int ret = 0;
736
737         wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
738
739         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
740         if (!cmd) {
741                 ret = -ENOMEM;
742                 goto out;
743         }
744
745         cmd->id = id;
746         cmd->key_action = KEY_SET_ID;
747         cmd->key_type = KEY_WEP;
748
749         ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
750         if (ret < 0) {
751                 wl1271_warning("cmd set_default_wep_key failed: %d", ret);
752                 goto out;
753         }
754
755 out:
756         kfree(cmd);
757
758         return ret;
759 }
760
761 int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
762                        u8 key_size, const u8 *key, const u8 *addr)
763 {
764         struct wl1271_cmd_set_keys *cmd;
765         int ret = 0;
766
767         cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
768         if (!cmd) {
769                 ret = -ENOMEM;
770                 goto out;
771         }
772
773         if (key_type != KEY_WEP)
774                 memcpy(cmd->addr, addr, ETH_ALEN);
775
776         cmd->key_action = action;
777         cmd->key_size = key_size;
778         cmd->key_type = key_type;
779
780         /* we have only one SSID profile */
781         cmd->ssid_profile = 0;
782
783         cmd->id = id;
784
785         /* FIXME: this is from wl1251, needs to be checked */
786         if (key_type == KEY_TKIP) {
787                 /*
788                  * We get the key in the following form:
789                  * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
790                  * but the target is expecting:
791                  * TKIP - RX MIC - TX MIC
792                  */
793                 memcpy(cmd->key, key, 16);
794                 memcpy(cmd->key + 16, key + 24, 8);
795                 memcpy(cmd->key + 24, key + 16, 8);
796
797         } else {
798                 memcpy(cmd->key, key, key_size);
799         }
800
801         wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd));
802
803         ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
804         if (ret < 0) {
805                 wl1271_warning("could not set keys");
806                 goto out;
807         }
808
809 out:
810         kfree(cmd);
811
812         return ret;
813 }