]> Git Repo - esp-hosted.git/blame - host/esp_cmd.c
Merge branch 'work_ng' into 'master'
[esp-hosted.git] / host / esp_cmd.c
CommitLineData
774e9b2e
MM
1/*
2 * Espressif Systems Wireless LAN device driver
3 *
4 * Copyright (C) 2015-2021 Espressif Systems (Shanghai) PTE LTD
5 *
6 * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "esp_cmd.h"
21#include "esp_api.h"
22#include "esp_wpa_utils.h"
23
24#define PRINT_HEXDUMP(STR,ARG, ARG_LEN,level) \
25 print_hex_dump(KERN_INFO, STR, DUMP_PREFIX_ADDRESS, 16, 1, ARG, ARG_LEN, 1);
26
27#define COMMAND_RESPONSE_TIMEOUT (5 * HZ)
28u8 ap_bssid[MAC_ADDR_LEN];
29
30int internal_scan_request(struct esp_wifi_device *priv, char* ssid,
31 uint8_t channel, uint8_t is_blocking);
32
33struct beacon_probe_fixed_params {
34 __le64 timestamp;
35 __le16 beacon_interval;
36 __le16 cap_info;
37} __packed;
38
39
40static struct command_node * get_free_cmd_node(struct esp_adapter *adapter)
41{
42 struct command_node *cmd_node;
43
44 spin_lock_bh(&adapter->cmd_free_queue_lock);
45
46 if (list_empty(&adapter->cmd_free_queue)) {
47 spin_unlock_bh(&adapter->cmd_free_queue_lock);
48 printk(KERN_ERR "esp32: No free cmd node found\n");
49 return NULL;
50 }
51 cmd_node = list_first_entry(&adapter->cmd_free_queue,
52 struct command_node, list);
53 list_del(&cmd_node->list);
54 spin_unlock_bh(&adapter->cmd_free_queue_lock);
55
56 cmd_node->cmd_skb = esp_alloc_skb(ESP_SIZE_OF_CMD_NODE);
57 if (!cmd_node->cmd_skb) {
58 printk(KERN_ERR "esp32: No free cmd node skb found\n");
59 }
60
61 return cmd_node;
62}
63
64static inline void reset_cmd_node(struct command_node * cmd_node)
65{
66 cmd_node->cmd_code = 0;
67
68 if (cmd_node->resp_skb) {
69 dev_kfree_skb_any(cmd_node->resp_skb);
70 cmd_node->resp_skb = NULL;
71 }
72}
73
74static void queue_cmd_node(struct esp_adapter *adapter,
75 struct command_node * cmd_node, u8 flag_high_prio)
76{
77 spin_lock_bh(&adapter->cmd_pending_queue_lock);
78
79 if (flag_high_prio)
80 list_add(&cmd_node->list, &adapter->cmd_pending_queue);
81 else
82 list_add_tail(&cmd_node->list, &adapter->cmd_pending_queue);
83
84 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
85}
86
87static int decode_get_mac_addr(struct esp_wifi_device *priv,
88 struct command_node *cmd_node)
89{
90 int ret = 0;
91 struct cmd_config_mac_address *header;
92
93 if (!priv || !cmd_node ||
94 !cmd_node->resp_skb ||
95 !cmd_node->resp_skb->data) {
96 printk(KERN_INFO "%s: invalid arg\n", __func__);
97 return -1;
98 }
99
100 header = (struct cmd_config_mac_address *) (cmd_node->resp_skb->data);
101
102 if (header->header.cmd_status != CMD_RESPONSE_SUCCESS) {
103 printk(KERN_INFO "esp32: Command failed\n");
104 ret = -1;
105 }
106
107 if (priv)
108 memcpy(priv->mac_address, header->mac_addr, MAC_ADDR_LEN);
109 else
110 printk(KERN_ERR "esp32: %s: priv not updated\n", __func__);
111
112 return ret;
113}
114
115
116static int decode_common_resp(struct command_node *cmd_node)
117{
118 int ret = 0;
119 struct command_header *cmd;
120
121
122 if (!cmd_node || !cmd_node->resp_skb || !cmd_node->resp_skb->data) {
123 printk(KERN_INFO "%s: invalid arg\n", __func__);
124 return -1;
125 }
126
127 cmd = (struct command_header *) (cmd_node->resp_skb->data);
128
129 if (cmd->cmd_status != CMD_RESPONSE_SUCCESS) {
130 printk(KERN_INFO "esp32: [0x%x] Command failed\n", cmd_node->cmd_code);
131 ret = -1;
132 }
133
134 return ret;
135}
136
137static void recycle_cmd_node(struct esp_adapter *adapter,
138 struct command_node * cmd_node)
139{
140 if (!adapter || !cmd_node)
141 return;
142
143 reset_cmd_node(cmd_node);
144
145 spin_lock_bh(&adapter->cmd_free_queue_lock);
146 list_add_tail(&cmd_node->list, &adapter->cmd_free_queue);
147 spin_unlock_bh(&adapter->cmd_free_queue_lock);
148}
149
150
151static int wait_and_decode_cmd_resp(struct esp_wifi_device *priv,
152 struct command_node *cmd_node)
153{
154 struct esp_adapter *adapter = NULL;
155 int ret = 0;
156
157 if (!priv || !priv->adapter || !cmd_node) {
158 printk(KERN_INFO "%s invalid params\n", __func__);
159 if (priv->adapter) {
160 adapter = priv->adapter;
161 if (adapter && cmd_node)
162 recycle_cmd_node(adapter, cmd_node);
163 }
164 return -EINVAL;
165 }
166
167 adapter = priv->adapter;
168
169 /* wait for command response */
170 ret = wait_event_interruptible_timeout(adapter->wait_for_cmd_resp,
171 adapter->cmd_resp != 0, COMMAND_RESPONSE_TIMEOUT);
172
173 if (ret == 0) {
174 printk(KERN_ERR "esp32: Command[%u] timed out\n",cmd_node->cmd_code);
175 ret = -EINVAL;
176 } else {
177 ret = 0;
178 }
179
180 spin_lock_bh(&adapter->cmd_lock);
181 adapter->cur_cmd = NULL;
182 adapter->cmd_resp = 0;
183 spin_unlock_bh(&adapter->cmd_lock);
184
185 switch (cmd_node->cmd_code) {
186
187 case CMD_SCAN_REQUEST:
188 if (ret == 0)
189 ret = decode_common_resp(cmd_node);
190
191 if (ret) {
059da5be
YM
192
193 struct cfg80211_scan_info info = {
194 .aborted = false,
195 };
196
197 if (priv->request)
198 cfg80211_scan_done(priv->request, &info);
199
774e9b2e
MM
200 priv->scan_in_progress = false;
201 priv->request = NULL;
202 }
203 break;
204
205 case CMD_INIT_INTERFACE:
206 case CMD_DEINIT_INTERFACE:
207 case CMD_STA_CONNECT:
208 case CMD_STA_DISCONNECT:
209 case CMD_ADD_KEY:
210 case CMD_DEL_KEY:
211 case CMD_SET_DEFAULT_KEY:
212 /* intentional fallthrough */
213 if (ret == 0)
214 ret = decode_common_resp(cmd_node);
215 break;
216
217 case CMD_GET_MAC:
218 if (ret == 0)
219 ret = decode_get_mac_addr(priv, cmd_node);
220 break;
221
222 default:
223 printk(KERN_INFO "esp32: %s Resp for [0x%x] ignored\n",
224 __func__,cmd_node->cmd_code);
225 ret = -EINVAL;
226 break;
227 }
228
229 recycle_cmd_node(adapter, cmd_node);
230 return ret;
231}
232
233static void free_esp_cmd_pool(struct esp_adapter *adapter)
234{
235 int i;
236 struct command_node * cmd_pool = NULL;
237
238 if (!adapter || !adapter->cmd_pool)
239 return;
240
241 cmd_pool = adapter->cmd_pool;
242
243 for (i=0; i<ESP_NUM_OF_CMD_NODES; i++) {
244
245 if (cmd_pool[i].resp_skb) {
246 dev_kfree_skb_any(cmd_pool[i].resp_skb);
247 cmd_pool[i].resp_skb = NULL;
248 }
249 }
250
251 kfree(adapter->cmd_pool);
252 adapter->cmd_pool = NULL;
253}
254
255static int alloc_esp_cmd_pool(struct esp_adapter *adapter)
256{
257 u16 i;
258
259 struct command_node * cmd_pool = kcalloc(ESP_NUM_OF_CMD_NODES,
260 sizeof(struct command_node), GFP_KERNEL);
261
262 if(!cmd_pool)
263 return -ENOMEM;
264
265 adapter->cmd_pool = cmd_pool;
266
267 for (i=0; i<ESP_NUM_OF_CMD_NODES; i++) {
268
269 cmd_pool[i].cmd_skb = NULL;
270 cmd_pool[i].resp_skb = NULL;
271 recycle_cmd_node(adapter, &cmd_pool[i]);
272 }
273
274 return 0;
275}
276
277#if 0
278static int is_command_pending(struct esp_adapter *adapter)
279{
280 int is_cmd_pend_q_empty;
281
282 spin_lock_bh(&adapter->cmd_pending_queue_lock);
283 is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_queue);
284 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
285
286 return !is_cmd_pend_q_empty;
287}
288#endif
289
290static void esp_cmd_work(struct work_struct *work)
291{
292 int ret;
293 struct command_node *cmd_node = NULL;
294 struct esp_adapter * adapter = NULL;
295
296 adapter = esp_get_adapter();
297
298 if (!adapter)
299 return;
300
301 if (adapter->cur_cmd) {
302 //TODO: there should be failure reported to
303 //cmd in progress. it should fail and not time out.
304 // applicable other neg cases also
305 return;
306 }
307
308 spin_lock_bh(&adapter->cmd_pending_queue_lock);
309
310 if (list_empty(&adapter->cmd_pending_queue)) {
311 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
312 return;
313 }
314
315 cmd_node = list_first_entry(&adapter->cmd_pending_queue,
316 struct command_node, list);
317 if (! cmd_node) {
318 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
319 return;
320 }
321 list_del(&cmd_node->list);
322
323 if (! cmd_node->cmd_skb) {
324 printk (KERN_ERR "cmd_node->cmd_skb NULL \n");
325 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
326 return;
327 }
328
329 spin_lock_bh(&adapter->cmd_lock);
330 adapter->cur_cmd = cmd_node;
331 adapter->cmd_resp = 0;
332 spin_unlock_bh(&adapter->cmd_lock);
333
334 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
335
336 ret = esp_send_packet(adapter, cmd_node->cmd_skb);
337
338 if (ret) {
339 printk (KERN_ERR "Failed to send command\n");
340 spin_lock_bh(&adapter->cmd_lock);
341 adapter->cur_cmd = NULL;
342 spin_unlock_bh(&adapter->cmd_lock);
343 recycle_cmd_node(adapter, cmd_node);
344 return;
345 }
346}
347
348static int create_cmd_wq(struct esp_adapter *adapter)
349{
350 adapter->cmd_wq = alloc_workqueue("ESP_CMD_WORK_QUEUE", 0, 0);
351
352 RET_ON_FAIL(!adapter->cmd_wq);
353
354 INIT_WORK(&adapter->cmd_work, esp_cmd_work);
355
356 return 0;
357}
358
359static void destroy_cmd_wq(struct esp_adapter *adapter)
360{
361 if (adapter->cmd_wq) {
362 flush_scheduled_work();
363 destroy_workqueue(adapter->cmd_wq);
364 adapter->cmd_wq = NULL;
365 }
366}
367
368struct command_node * prepare_command_request(struct esp_adapter *adapter, u8 cmd_code, u16 len)
369{
370 struct command_header *cmd;
371 struct esp_payload_header *payload_header;
372 struct command_node *node = NULL;
373
374 if (!adapter) {
375 printk(KERN_INFO "%s:%u null adapter\n",__func__,__LINE__);
376 return NULL;
377 }
378
379 if (!cmd_code || cmd_code >= CMD_MAX) {
380 printk (KERN_ERR "esp32: %s: unsupported command code\n", __func__);
381 return NULL;
382 }
383
384 node = get_free_cmd_node(adapter);
385
386 if (!node || !node->cmd_skb) {
387 printk (KERN_ERR "esp32: %s: Failed to get new free cmd node\n", __func__);
388 return NULL;
389 }
390
391 node->cmd_code = cmd_code;
392
393 len += sizeof(struct esp_payload_header);
394
395 payload_header = skb_put(node->cmd_skb, len);
396 memset(payload_header, 0, len);
397
398 payload_header->if_type = ESP_STA_IF;
399 payload_header->len = cpu_to_le16(len - sizeof(struct esp_payload_header));
400 payload_header->offset = cpu_to_le16(sizeof(struct esp_payload_header));
401 payload_header->packet_type = PACKET_TYPE_COMMAND_REQUEST;
402
403 cmd = (struct command_header *) (node->cmd_skb->data + payload_header->offset);
404 cmd->cmd_code = cmd_code;
405
406/* payload_header->checksum = cpu_to_le16(compute_checksum(skb->data, len));*/
407
408 return node;
409}
410
411int process_command_response(struct esp_adapter *adapter, struct sk_buff *skb)
412{
413 if (!skb || !adapter) {
414 printk (KERN_ERR "esp32: CMD resp: invalid!\n");
415
416 if (skb)
417 dev_kfree_skb_any(skb);
418
419 return -1;
420 }
421
422 if (!adapter->cur_cmd) {
423 printk (KERN_ERR "esp32: Command response not expected\n");
424 dev_kfree_skb_any(skb);
425 return -1;
426 }
427
428 spin_lock_bh(&adapter->cmd_lock);
429 adapter->cur_cmd->resp_skb = skb;
430 spin_unlock_bh(&adapter->cmd_lock);
431
432 adapter->cmd_resp = 1;
433
434 wake_up_interruptible(&adapter->wait_for_cmd_resp);
435 queue_work(adapter->cmd_wq, &adapter->cmd_work);
436
437 return 0;
438}
439
440static void process_scan_result_event(struct esp_wifi_device *priv,
441 struct scan_event *scan_evt)
442{
443 struct cfg80211_bss *bss;
444 struct beacon_probe_fixed_params *fixed_params;
445 u64 timestamp;
446 u16 beacon_interval;
447 u16 cap_info;
448 u8 *ie_buf;
449 u32 ie_len;
450 int freq;
451 struct ieee80211_channel *chan;
452
453 if (!priv || !scan_evt) {
454 printk(KERN_ERR "%s: Invalid arguments\n", __func__);
455 return;
456 }
457
458 /* End of scan; notify cfg80211 */
459 if (scan_evt->header.status == 0) {
460 struct cfg80211_scan_info info = {
461 .aborted = false,
462 };
463
464 if (priv->request) {
465 /* scan completion */
466 cfg80211_scan_done(priv->request, &info);
467 priv->request = NULL;
468 }
469
470 priv->scan_in_progress = false;
471
472 if (priv->waiting_for_scan_done) {
473 priv->waiting_for_scan_done = false;
474 wake_up_interruptible(&priv->wait_for_scan_completion);
475 }
476 return;
477 }
478
479 ie_buf = (u8 *) scan_evt->frame;
480 ie_len = le16_to_cpu(scan_evt->frame_len);
481
482 fixed_params = (struct beacon_probe_fixed_params *) ie_buf;
483
484 timestamp = le64_to_cpu(fixed_params->timestamp);
485 beacon_interval = le16_to_cpu(fixed_params->beacon_interval);
486 cap_info = le16_to_cpu(fixed_params->cap_info);
487
488 freq = ieee80211_channel_to_frequency(scan_evt->channel, NL80211_BAND_2GHZ);
489 chan = ieee80211_get_channel(priv->adapter->wiphy, freq);
490
491 ie_buf += sizeof(struct beacon_probe_fixed_params);
492 ie_len -= sizeof(struct beacon_probe_fixed_params);
493
494 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
495 bss = cfg80211_inform_bss(priv->adapter->wiphy, chan,
496 CFG80211_BSS_FTYPE_UNKNOWN, scan_evt->bssid, timestamp,
497 cap_info, beacon_interval, ie_buf, ie_len,
498 le32_to_cpu(scan_evt->rssi), GFP_ATOMIC);
499
500 if (bss)
501 cfg80211_put_bss(priv->adapter->wiphy, bss);
502 } else {
503 printk (KERN_INFO "Scan report: Skip invalid or disabled channel\n");
504 }
505}
506
507static void process_disconnect_event(struct esp_wifi_device *priv,
508 struct disconnect_event *event)
509{
510 if (!priv || !event) {
511 printk(KERN_ERR "%s: Invalid arguments\n", __func__);
512 return;
513 }
514
515 printk(KERN_INFO "Disconnect event for ssid %s [%d]\n", event->ssid,
516 event->reason);
517
518 esp_port_close(priv);
519 if (priv->ndev)
520 cfg80211_disconnected(priv->ndev, event->reason, NULL, 0, true,
521 GFP_KERNEL);
522}
523
524static void process_connect_status_event(struct esp_wifi_device *priv,
525 struct connect_event *event)
526{
527 u8 mac[6];
528
529 if (!priv || !event) {
530 printk(KERN_ERR "%s: Invalid arguments\n", __func__);
531 return;
532 }
533
534 printk(KERN_INFO "Connection status: %d\n", event->header.status);
535
536 if (!event->bssid) {
537 printk(KERN_INFO "bssid input as NULL. Ignoring the connect statuc event\n");
538 return;
539 }
540 memcpy(mac, event->bssid, MAC_ADDR_LEN);
541
542 cfg80211_connect_result(priv->ndev, mac, NULL, 0, NULL, 0,
543 0, GFP_KERNEL);
544
545 esp_port_open(priv);
546}
547
548int process_event(struct esp_wifi_device *priv, struct sk_buff *skb)
549{
550 struct event_header *header;
551
552 if (!skb || !priv) {
553 printk (KERN_ERR "esp32: CMD resp: invalid!\n");
554
555 if (skb)
556 dev_kfree_skb_any(skb);
557
558 return -1;
559 }
560
561 header = (struct event_header *) (skb->data);
562
563 switch (header->event_code) {
564
565 case EVENT_SCAN_RESULT:
566 process_scan_result_event(priv,
567 (struct scan_event *)(skb->data));
568 break;
569
570 case EVENT_STA_CONNECT:
571 process_connect_status_event(priv,
572 (struct connect_event *)(skb->data));
573 break;
574
575 case EVENT_STA_DISCONNECT:
576 process_disconnect_event(priv,
577 (struct disconnect_event *)(skb->data));
578 break;
579
580 default:
581 printk(KERN_INFO "%s:%u unhandled event[%u]\n",
582 __func__, __LINE__, header->event_code);
583 break;
584 }
585
586 return 0;
587}
588
589int cmd_disconnect_request(struct esp_wifi_device *priv, u16 reason_code)
590{
591 struct command_node *cmd_node = NULL;
592 struct cmd_sta_disconnect *cmd_disconnect;
593
594 if (!priv || !priv->adapter) {
595 printk(KERN_ERR "%s: Invalid argument\n", __func__);
596 return -EINVAL;
597 }
598
599 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
600 return 0;
601
602 cmd_node = prepare_command_request(priv->adapter, CMD_STA_DISCONNECT,
603 sizeof(struct cmd_sta_disconnect));
604
605 if (!cmd_node) {
606 printk(KERN_ERR "Failed to get command node\n");
607 return -ENOMEM;
608 }
609
610 cmd_disconnect = (struct cmd_sta_disconnect *)
611 (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
612
613 cmd_disconnect->reason_code = reason_code;
614
615 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
616 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
617
618 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
619
620 return 0;
621}
622
623int cmd_connect_request(struct esp_wifi_device *priv,
624 struct cfg80211_connect_params *params)
625{
626 u16 cmd_len;
627 struct command_node *cmd_node = NULL;
628 struct cmd_sta_connect *cmd;
629 struct ieee80211_channel *chan;
630 struct cfg80211_bss *bss;
631 struct esp_adapter *adapter = NULL;
632
633 u8 retry = 2;
634
635 if (!priv || !params || !priv->adapter) {
636 printk(KERN_ERR "%s: Invalid argument\n", __func__);
637 return -EINVAL;
638 }
639
640 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
641 printk(KERN_ERR "%s:%u cleanup in progress, return failure", __func__, __LINE__);
642 return -EFAULT;
643 }
644
645 adapter = priv->adapter;
646
647 cmd_len = sizeof(struct cmd_sta_connect) + params->ie_len;
648
649 cmd_node = prepare_command_request(adapter, CMD_STA_CONNECT, cmd_len);
650 if (!cmd_node) {
651 printk(KERN_ERR "Failed to get command node\n");
652 return -ENOMEM;
653 }
654 cmd = (struct cmd_sta_connect *) (cmd_node->cmd_skb->data + sizeof(struct esp_payload_header));
655
656 if (params->ssid_len)
657 memcpy(cmd->ssid, params->ssid, MAX_SSID_LEN);
658 else
659 printk(KERN_ERR "%s: No ssid\n", __func__);
660
661 if (params->bssid) {
662 memcpy(ap_bssid, params->bssid, MAC_ADDR_LEN);
663 memcpy(cmd->bssid, params->bssid, MAC_ADDR_LEN);
664 }
665
666 if (params->channel) {
667 chan = params->channel;
668 cmd->channel = chan->hw_value;
669 }
670
671 if (params->ie_len) {
672 cmd->assoc_ie_len = cpu_to_le16(params->ie_len);
673 memcpy(cmd->assoc_ie, params->ie, params->ie_len);
674 }
675
676 if (params->privacy)
677 cmd->is_auth_open = 0;
678 else
679 cmd->is_auth_open = 1;
680
681 printk (KERN_INFO "Connection request: %s %pM %d\n",
682 cmd->ssid, params->bssid, cmd->channel);
683
684 do {
685 bss = cfg80211_get_bss(adapter->wiphy, params->channel, params->bssid,
686 params->ssid, params->ssid_len, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
687
688 if (bss) {
689 break;
690 } else {
691 printk (KERN_INFO "No BSS in the list.. scanning..\n");
692 internal_scan_request(priv, cmd->ssid, cmd->channel, true);
693 }
694
695 retry--;
696 } while (retry);
697
698 if (retry) {
699 queue_cmd_node(adapter, cmd_node, ESP_CMD_DFLT_PRIO);
700 queue_work(adapter->cmd_wq, &adapter->cmd_work);
701
702 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
703 } else {
704 printk(KERN_INFO "Failed to find %s\n", cmd->ssid);
705 return -EFAULT;
706 }
707
708 return 0;
709}
710
711int cmd_set_default_key(struct esp_wifi_device *priv, u8 key_index)
712{
713 u16 cmd_len;
714 struct command_node *cmd_node = NULL;
715 struct cmd_key_operation *cmd;
716 struct wifi_sec_key * key = NULL;
717
718 if (!priv || !priv->adapter) {
719 printk(KERN_ERR "%s: Invalid argument\n", __func__);
720 return -EINVAL;
721 }
722
723#if 0
724 if (key_index > ESP_MAX_KEY_INDEX) {
725 printk(KERN_ERR "invalid key index[%u] > max[%u]\n",
726 key_index, ESP_MAX_KEY_INDEX);
727 return -EINVAL;
728 }
729#endif
730 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
731 printk(KERN_ERR "%s:%u cleanup in progress, return", __func__, __LINE__);
732 return 0;
733 }
734
735
736 cmd_len = sizeof(struct cmd_key_operation);
737
738 /* get new cmd node */
739 cmd_node = prepare_command_request(priv->adapter, CMD_SET_DEFAULT_KEY, cmd_len);
740 if (!cmd_node) {
741 printk(KERN_ERR "Failed to get command node\n");
742 return -ENOMEM;
743 }
744
745 /* cmd specific update */
746 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
747 sizeof(struct esp_payload_header));
748 key = &cmd->key;
749
750 key->index = key_index;
751 key->set_cur = 1;
752
753 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
754 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
755
756 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
757
758 return 0;
759}
760
761int cmd_del_key(struct esp_wifi_device *priv, u8 key_index, bool pairwise,
762 const u8 *mac_addr)
763{
764 u16 cmd_len;
765 struct command_node *cmd_node = NULL;
766 struct cmd_key_operation *cmd;
767 struct wifi_sec_key * key = NULL;
768 const u8 *mac = NULL;
769 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
770
771 if (!priv || !priv->adapter) {
772 printk(KERN_ERR "%s: Invalid argument\n", __func__);
773 return -EINVAL;
774 }
775
776 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags))
777 return 0;
778
779#if 0
780 if (key_index > ESP_MAX_KEY_INDEX) {
781 printk(KERN_ERR "invalid key index[%u] > max[%u]\n",
782 key_index, ESP_MAX_KEY_INDEX);
783 return -EINVAL;
784 }
785#endif
786
787 mac = pairwise ? mac_addr : bc_mac;
788 print_hex_dump(KERN_INFO, "mac_addr: ", DUMP_PREFIX_ADDRESS, 16, 1,
789 mac, MAC_ADDR_LEN, 1);
790
791 cmd_len = sizeof(struct cmd_key_operation);
792
793 /* get new cmd node */
794 cmd_node = prepare_command_request(priv->adapter, CMD_DEL_KEY, cmd_len);
795 if (!cmd_node) {
796 printk(KERN_ERR "Failed to get command node\n");
797 return -ENOMEM;
798 }
799
800 /* cmd specific update */
801 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
802 sizeof(struct esp_payload_header));
803 key = &cmd->key;
804
805 if (mac && !is_multicast_ether_addr(mac))
806 memcpy((char *)&key->mac_addr, (void *)mac, MAC_ADDR_LEN);
807
808 key->index = key_index;
809 key->del = 1;
810
811 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
812 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
813
814 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
815
816 return 0;
817}
818
819int cmd_add_key(struct esp_wifi_device *priv, u8 key_index, bool pairwise,
820 const u8 *mac_addr, struct key_params *params)
821{
822 u16 cmd_len;
823 struct command_node *cmd_node = NULL;
824 struct cmd_key_operation *cmd;
825 struct wifi_sec_key * key = NULL;
826 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
827 const u8 *mac = NULL;
828
829#if 0
830 printk(KERN_INFO "%s:%u key_idx: %u pairwise: %u params->key_len: %u \nparams->seq_len:%u params->mode: 0x%x \nparams->cipher: 0x%x\n",
831 __func__, __LINE__,
832 key_index, pairwise, params->key_len, params->seq_len, params->mode, params->cipher);
833#endif
834 if (!priv || !priv->adapter || !params ||
835 !params->key || !params->key_len || !params->seq_len) {
836 printk(KERN_ERR "%s: Invalid argument\n", __func__);
837 return -EINVAL;
838 }
839
840#if 0
841 if (key_index > ESP_MAX_KEY_INDEX) {
842 printk(KERN_ERR "invalid key index[%u] > max[%u]\n",
843 key_index, ESP_MAX_KEY_INDEX);
844 return -EINVAL;
845 }
846#endif
847
848 if (params->key_len > sizeof(key->data)) {
849 printk(KERN_ERR "Too long key length (%u)\n", params->key_len);
850 return -EINVAL;
851 }
852
853 if (params->seq_len > sizeof(key->seq)) {
854 printk(KERN_ERR "Too long key seq length (%u)\n", params->seq_len);
855 return -EINVAL;
856 }
857
858 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
859 printk(KERN_ERR "%s:%u cleanup in progress, return failure", __func__, __LINE__);
860 return -EFAULT;
861 }
862
863 mac = pairwise ? mac_addr : bc_mac;
864 if (mac) {
865 print_hex_dump(KERN_INFO, "mac: ", DUMP_PREFIX_ADDRESS, 16, 1,
866 mac, MAC_ADDR_LEN, 1);
867 }
868
869 cmd_len = sizeof(struct cmd_key_operation);
870
871 cmd_node = prepare_command_request(priv->adapter, CMD_ADD_KEY, cmd_len);
872 if (!cmd_node) {
873 printk(KERN_ERR "Failed to get command node\n");
874 return -ENOMEM;
875 }
876
877 cmd = (struct cmd_key_operation *) (cmd_node->cmd_skb->data +
878 sizeof(struct esp_payload_header));
879 key = &cmd->key;
880
881 if (mac && !is_multicast_ether_addr(mac))
882 memcpy((char *)&key->mac_addr, (void *)mac, MAC_ADDR_LEN);
883
884 key->index = key_index;
885
886 key->len = params->key_len;
887 if (params->key && key->len)
888 memcpy(key->data, params->key, key->len);
889
890 key->seq_len = params->seq_len;
891 if (params->seq && key->seq_len)
892 memcpy(key->seq, params->seq, key->seq_len);
893
894 key->set_tx = params->mode & NL80211_KEY_SET_TX;
895
896 key->algo = wpa_cipher_to_alg(params->cipher);
897#if 0
898 if (key->algo == WIFI_WPA_ALG_NONE) {
899 printk(KERN_INFO "CIPHER NONE does not use pairwise keys");
900 return 0;
901 }
902#endif
903
904#if 0
905 printk(KERN_ERR "%s:%u algo: %u idx: %u set_tx: %u seq_len: %u len:%u \n", __func__, __LINE__,
906 key->algo, key->index, key->set_tx, key->seq_len, key->len);
907 PRINT_HEXDUMP("mac", key->mac_addr, 6, ESP_LOG_INFO);
908 PRINT_HEXDUMP("seq", key->seq, key->seq_len, ESP_LOG_INFO);
909 PRINT_HEXDUMP("key_data", key->data, key->len, ESP_LOG_INFO);
910#endif
911
912 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
913 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
914
915 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
916
917 return 0;
918}
919
920int cmd_init_interface(struct esp_wifi_device *priv)
921{
922 u16 cmd_len;
923 struct command_node *cmd_node = NULL;
924
925 if (!priv || !priv->adapter) {
926 printk(KERN_ERR "%s: Invalid argument\n", __func__);
927 return -EINVAL;
928 }
929
930 cmd_len = sizeof(struct command_header);
931
932 cmd_node = prepare_command_request(priv->adapter, CMD_INIT_INTERFACE, cmd_len);
933
934 if (!cmd_node) {
935 printk(KERN_ERR "esp32: Failed to get command node\n");
936 return -ENOMEM;
937 }
938
939 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
940 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
941
942 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
943
944 return 0;
945}
946
947int cmd_deinit_interface(struct esp_wifi_device *priv)
948{
949 u16 cmd_len;
950 struct command_node *cmd_node = NULL;
951
952 if (!priv || !priv->adapter)
953 return -EINVAL;
954
955 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
956 printk(KERN_ERR "%s:%u cleanup in progress, return\n", __func__, __LINE__);
957 return 0;
958 }
959
960 cmd_len = sizeof(struct command_header);
961
962 cmd_node = prepare_command_request(priv->adapter, CMD_DEINIT_INTERFACE, cmd_len);
963
964 if (!cmd_node) {
965 printk(KERN_ERR "esp32: Failed to get command node\n");
966 return -ENOMEM;
967 }
968
969 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
970 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
971
972 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
973
974 return 0;
975}
976
977int internal_scan_request(struct esp_wifi_device *priv, char* ssid,
978 uint8_t channel, uint8_t is_blocking)
979{
980 int ret = 0;
981 u16 cmd_len;
982 struct command_node *cmd_node = NULL;
983 struct scan_request *scan_req;
984
985 if (!priv || !priv->adapter) {
986 printk(KERN_ERR "%s: Invalid argument\n", __func__);
987 return -EINVAL;
988 }
989
990 if (priv->scan_in_progress) {
991 printk(KERN_ERR "Scan in progress.. return\n");
992 return -EBUSY;
993 }
994
995 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
996 printk(KERN_ERR "%s:%u cleanup in progress, return", __func__, __LINE__);
059da5be 997 return -EBUSY;
774e9b2e
MM
998 }
999
1000 cmd_len = sizeof(struct scan_request);
1001
1002 cmd_node = prepare_command_request(priv->adapter, CMD_SCAN_REQUEST, cmd_len);
1003
1004 if (!cmd_node) {
1005 printk(KERN_ERR "esp32: Failed to get command node\n");
1006 return -ENOMEM;
1007 }
1008
1009 scan_req = (struct scan_request *) (cmd_node->cmd_skb->data +
1010 sizeof(struct esp_payload_header));
1011
1012 if (ssid) {
1013 memcpy(scan_req->ssid, ssid, MAX_SSID_LEN);
1014 }
1015
1016 scan_req->channel = channel;
1017
1018 priv->scan_in_progress = true;
1019
1020 if (is_blocking)
1021 priv->waiting_for_scan_done = true;
1022
1023 /* Enqueue command */
1024 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1025 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1026
1027 ret = wait_and_decode_cmd_resp(priv, cmd_node);
1028
1029 if (!ret && is_blocking) {
1030 /* Wait for scan done */
1031 wait_event_interruptible_timeout(priv->wait_for_scan_completion,
1032 priv->waiting_for_scan_done != true, COMMAND_RESPONSE_TIMEOUT);
1033 }
1034
1035 return ret;
1036}
1037
1038int cmd_scan_request(struct esp_wifi_device *priv, struct cfg80211_scan_request *request)
1039{
1040 u16 cmd_len;
1041 struct command_node *cmd_node = NULL;
1042 struct scan_request *scan_req;
1043
1044 if (!priv || !priv->adapter || !request) {
1045 printk(KERN_ERR "%s: Invalid argument\n", __func__);
1046 return -EINVAL;
1047 }
1048
1049 if (test_bit(ESP_CLEANUP_IN_PROGRESS, &priv->adapter->state_flags)) {
1050 printk(KERN_ERR "%s:%u cleanup in progress, return", __func__, __LINE__);
059da5be 1051 return -EBUSY;
774e9b2e
MM
1052 }
1053
1054
1055 if (priv->scan_in_progress || priv->request) {
1056 printk(KERN_ERR "Scan in progress.. return\n");
1057 return -EBUSY;
1058 }
1059
1060 cmd_len = sizeof(struct scan_request);
1061
1062 cmd_node = prepare_command_request(priv->adapter, CMD_SCAN_REQUEST, cmd_len);
1063
1064 if (!cmd_node) {
1065 printk(KERN_ERR "esp32: Failed to get command node\n");
1066 return -ENOMEM;
1067 }
1068
1069 scan_req = (struct scan_request *) (cmd_node->cmd_skb->data +
1070 sizeof(struct esp_payload_header));
1071
1072 /* TODO: Handle case of multiple SSIDs or channels */
1073 if(request->ssids[0].ssid_len) {
1074 memcpy(scan_req->ssid, request->ssids[0].ssid, MAX_SSID_LEN);
1075 }
1076
1077#if 0
1078 if (request->n_channels) {
1079 chan = request->channels[0];
1080 scan_req->channel = chan->hw_value;
1081 }
1082#endif
1083
1084 scan_req->duration = request->duration;
1085 memcpy(scan_req->bssid, request->bssid, MAC_ADDR_LEN);
1086
1087 priv->scan_in_progress = true;
1088 priv->request = request;
1089
1090 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1091 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1092
1093 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1094
1095 return 0;
1096}
1097
1098
1099int cmd_get_mac(struct esp_wifi_device *priv)
1100{
1101 u16 cmd_len;
1102 struct command_node *cmd_node = NULL;
1103
1104 if (!priv || !priv->adapter) {
1105 printk(KERN_ERR "%s: Invalid argument\n", __func__);
1106 return -EINVAL;
1107 }
1108
1109 cmd_len = sizeof(struct command_header);
1110
1111 cmd_node = prepare_command_request(priv->adapter, CMD_GET_MAC, cmd_len);
1112
1113 if (!cmd_node) {
1114 printk(KERN_ERR "esp32: Failed to get command node\n");
1115 return -ENOMEM;
1116 }
1117
1118 queue_cmd_node(priv->adapter, cmd_node, ESP_CMD_DFLT_PRIO);
1119 queue_work(priv->adapter->cmd_wq, &priv->adapter->cmd_work);
1120
1121 RET_ON_FAIL(wait_and_decode_cmd_resp(priv, cmd_node));
1122
1123 return 0;
1124}
1125
1126
1127int deinit_esp_dev(struct esp_adapter *adapter)
1128{
1129#define MAX_DEINIT_RETRY 5
1130 uint8_t iface_idx = 0;
1131
1132 if (!adapter) {
1133 return -EINVAL;
1134 }
1135
1136 set_bit(ESP_CLEANUP_IN_PROGRESS, &adapter->state_flags);
1137
1138 if (!test_bit(ESP_CMD_INIT_DONE, &adapter->state_flags))
1139 return 0;
1140
1141 wake_up_interruptible(&adapter->wait_for_cmd_resp);
1142 spin_lock_bh(&adapter->cmd_pending_queue_lock);
1143
1144 for (iface_idx=0; iface_idx<ESP_MAX_INTERFACE; iface_idx++) {
1145 if (adapter->priv[iface_idx] &&
1146 adapter->priv[iface_idx]->ndev &&
1147 adapter->priv[iface_idx]->wdev.current_bss)
1148 cfg80211_disconnected(adapter->priv[iface_idx]->ndev, 0, NULL, 0, false,
1149 GFP_KERNEL);
1150
1151 esp_port_close(adapter->priv[iface_idx]);
1152 }
1153
1154 list_del(&adapter->cmd_pending_queue);
1155 spin_unlock_bh(&adapter->cmd_pending_queue_lock);
1156
1157 spin_lock_bh(&adapter->cmd_free_queue_lock);
1158 list_del(&adapter->cmd_free_queue);
1159 spin_unlock_bh(&adapter->cmd_free_queue_lock);
1160
1161 destroy_cmd_wq(adapter);
1162 free_esp_cmd_pool(adapter);
1163
1164 return 0;
1165}
1166
1167int init_esp_dev(struct esp_adapter *adapter)
1168{
1169 if (!adapter) {
1170 printk(KERN_ERR "esp32: %s failed\n", __func__);
1171 return -EINVAL;
1172 }
1173
1174 init_waitqueue_head(&adapter->wait_for_cmd_resp);
1175
1176 spin_lock_init(&adapter->cmd_lock);
1177
1178 INIT_LIST_HEAD(&adapter->cmd_pending_queue);
1179 INIT_LIST_HEAD(&adapter->cmd_free_queue);
1180
1181 spin_lock_init(&adapter->cmd_pending_queue_lock);
1182 spin_lock_init(&adapter->cmd_free_queue_lock);
1183
1184 RET_ON_FAIL(create_cmd_wq(adapter));
1185
1186 RET_ON_FAIL(alloc_esp_cmd_pool(adapter));
1187
1188 set_bit(ESP_CMD_INIT_DONE, &adapter->state_flags);
1189 return 0;
1190}
1191
This page took 0.150463 seconds and 4 git commands to generate.