source: mainline/uspace/drv/nic/ar9271/ar9271.c@ cc575ef9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cc575ef9 was a931b7b, checked in by Jan Kolarik <kolarik@…>, 10 years ago

Added TKIP support, handling old WPA in 4way handshake, some fixes in wifi_supplicant app

  • Property mode set to 100644
File size: 25.7 KB
Line 
1/*
2 * Copyright (c) 2014 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file ar9271.c
30 *
31 * Driver for AR9271 USB WiFi dongle.
32 *
33 */
34
35#include <ieee80211.h>
36#include <usb/classes/classes.h>
37#include <usb/dev/request.h>
38#include <usb/dev/poll.h>
39#include <usb/debug.h>
40#include <stdio.h>
41#include <ddf/interrupt.h>
42#include <nic.h>
43#include <macros.h>
44
45#include "ath_usb.h"
46#include "wmi.h"
47#include "hw.h"
48#include "ar9271.h"
49
50#define NAME "ar9271"
51#define FIRMWARE_FILENAME "/drv/ar9271/ar9271.fw"
52
53const usb_endpoint_description_t usb_ar9271_out_bulk_endpoint_description = {
54 .transfer_type = USB_TRANSFER_BULK,
55 .direction = USB_DIRECTION_OUT,
56 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
57 .interface_subclass = 0x0,
58 .interface_protocol = 0x0,
59 .flags = 0
60};
61
62const usb_endpoint_description_t usb_ar9271_in_bulk_endpoint_description = {
63 .transfer_type = USB_TRANSFER_BULK,
64 .direction = USB_DIRECTION_IN,
65 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
66 .interface_subclass = 0x0,
67 .interface_protocol = 0x0,
68 .flags = 0
69};
70
71const usb_endpoint_description_t usb_ar9271_in_int_endpoint_description = {
72 .transfer_type = USB_TRANSFER_INTERRUPT,
73 .direction = USB_DIRECTION_IN,
74 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
75 .interface_subclass = 0x0,
76 .interface_protocol = 0x0,
77 .flags = 0
78};
79
80const usb_endpoint_description_t usb_ar9271_out_int_endpoint_description = {
81 .transfer_type = USB_TRANSFER_INTERRUPT,
82 .direction = USB_DIRECTION_OUT,
83 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
84 .interface_subclass = 0x0,
85 .interface_protocol = 0x0,
86 .flags = 0
87};
88
89/* Array of endpoints expected on the device, NULL terminated. */
90const usb_endpoint_description_t *endpoints[] = {
91 &usb_ar9271_out_bulk_endpoint_description,
92 &usb_ar9271_in_bulk_endpoint_description,
93 &usb_ar9271_in_int_endpoint_description,
94 &usb_ar9271_out_int_endpoint_description,
95 NULL
96};
97
98/* Callback when new device is to be controlled by this driver. */
99static int ar9271_add_device(ddf_dev_t *);
100
101/* IEEE 802.11 callbacks */
102static int ar9271_ieee80211_start(ieee80211_dev_t *ieee80211_dev);
103static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *ieee80211_dev,
104 void *buffer, size_t buffer_size);
105static int ar9271_ieee80211_set_freq(ieee80211_dev_t *ieee80211_dev,
106 uint16_t freq);
107static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev,
108 bool connected);
109static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev,
110 ieee80211_key_config_t *key_conf, bool insert);
111
112static driver_ops_t ar9271_driver_ops = {
113 .dev_add = ar9271_add_device
114};
115
116static driver_t ar9271_driver = {
117 .name = NAME,
118 .driver_ops = &ar9271_driver_ops
119};
120
121static ieee80211_ops_t ar9271_ieee80211_ops = {
122 .start = ar9271_ieee80211_start,
123 .tx_handler = ar9271_ieee80211_tx_handler,
124 .set_freq = ar9271_ieee80211_set_freq,
125 .bssid_change = ar9271_ieee80211_bssid_change,
126 .key_config = ar9271_ieee80211_key_config
127};
128
129static ieee80211_iface_t ar9271_ieee80211_iface;
130
131static int ar9271_get_device_info(ddf_fun_t *dev, nic_device_info_t *info);
132static int ar9271_get_cable_state(ddf_fun_t *, nic_cable_state_t *);
133static int ar9271_get_operation_mode(ddf_fun_t *, int *,
134 nic_channel_mode_t *, nic_role_t *);
135
136static nic_iface_t ar9271_ieee80211_nic_iface = {
137 .get_device_info = &ar9271_get_device_info,
138 .get_cable_state = &ar9271_get_cable_state,
139 .get_operation_mode = &ar9271_get_operation_mode
140};
141
142static ddf_dev_ops_t ar9271_ieee80211_dev_ops;
143
144/**
145 * Get device information.
146 *
147 */
148static int ar9271_get_device_info(ddf_fun_t *dev, nic_device_info_t *info)
149{
150 assert(dev);
151 assert(info);
152
153 memset(info, 0, sizeof(nic_device_info_t));
154
155 info->vendor_id = 0x0CF3;
156 info->device_id = 0x9271;
157 str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH,
158 "Atheros Communications, Inc.");
159 str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH,
160 "AR9271");
161
162 return EOK;
163}
164
165/**
166 * Get cable state.
167 *
168 */
169static int ar9271_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state)
170{
171 *state = NIC_CS_PLUGGED;
172
173 return EOK;
174}
175
176/**
177 * Get operation mode of the device.
178 *
179 */
180static int ar9271_get_operation_mode(ddf_fun_t *fun, int *speed,
181 nic_channel_mode_t *duplex, nic_role_t *role)
182{
183 *duplex = NIC_CM_FULL_DUPLEX;
184 *speed = 10;
185 *role = NIC_ROLE_UNKNOWN;
186
187 return EOK;
188}
189
190/**
191 * Set multicast frames acceptance mode.
192 *
193 */
194static int ar9271_on_multicast_mode_change(nic_t *nic,
195 nic_multicast_mode_t mode, const nic_address_t *addr, size_t addr_cnt)
196{
197 /*
198 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *)
199 nic_get_specific(nic);
200 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
201 */
202
203 switch (mode) {
204 case NIC_MULTICAST_BLOCKED:
205 /* TODO */
206 break;
207 case NIC_MULTICAST_LIST:
208 /* TODO */
209 break;
210 case NIC_MULTICAST_PROMISC:
211 /* TODO */
212 break;
213 default:
214 return ENOTSUP;
215 }
216
217 return EOK;
218}
219
220/**
221 * Set unicast frames acceptance mode.
222 *
223 */
224static int ar9271_on_unicast_mode_change(nic_t *nic, nic_unicast_mode_t mode,
225 const nic_address_t *addr, size_t addr_cnt)
226{
227 /*
228 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *)
229 nic_get_specific(nic);
230 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
231 */
232
233 switch (mode) {
234 case NIC_UNICAST_BLOCKED:
235 /* TODO */
236 break;
237 case NIC_UNICAST_DEFAULT:
238 /* TODO */
239 break;
240 case NIC_UNICAST_LIST:
241 /* TODO */
242 break;
243 case NIC_UNICAST_PROMISC:
244 /* TODO */
245 break;
246 default:
247 return ENOTSUP;
248 }
249
250 return EOK;
251}
252
253/**
254 * Set broadcast frames acceptance mode.
255 *
256 */
257static int ar9271_on_broadcast_mode_change(nic_t *nic,
258 nic_broadcast_mode_t mode)
259{
260 /*
261 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *)
262 nic_get_specific(nic);
263 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
264 */
265
266 switch (mode) {
267 case NIC_BROADCAST_BLOCKED:
268 /* TODO */
269 break;
270 case NIC_BROADCAST_ACCEPTED:
271 /* TODO */
272 break;
273 default:
274 return ENOTSUP;
275 }
276
277 return EOK;
278}
279
280static bool ar9271_rx_status_error(uint8_t status)
281{
282 return (status & AR9271_RX_ERROR_PHY) || (status & AR9271_RX_ERROR_CRC);
283}
284
285static int ar9271_data_polling(void *arg)
286{
287 assert(arg);
288
289 ar9271_t *ar9271 = (ar9271_t *) arg;
290
291 size_t buffer_size = ar9271->ath_device->data_response_length;
292 void *buffer = malloc(buffer_size);
293
294 while(true) {
295 size_t transferred_size;
296 if(htc_read_data_message(ar9271->htc_device,
297 buffer, buffer_size, &transferred_size) == EOK) {
298 size_t strip_length =
299 sizeof(ath_usb_data_header_t) +
300 sizeof(htc_frame_header_t) +
301 sizeof(htc_rx_status_t);
302
303 if(transferred_size < strip_length)
304 continue;
305
306 ath_usb_data_header_t *data_header =
307 (ath_usb_data_header_t *) buffer;
308
309 /* Invalid packet. */
310 if(data_header->tag != uint16_t_le2host(RX_TAG))
311 continue;
312
313 htc_rx_status_t *rx_status =
314 (htc_rx_status_t *) ((void *) buffer +
315 sizeof(ath_usb_data_header_t) +
316 sizeof(htc_frame_header_t));
317
318 uint16_t data_length =
319 uint16_t_be2host(rx_status->data_length);
320
321 int16_t payload_length =
322 transferred_size - strip_length;
323
324 if(payload_length - data_length < 0)
325 continue;
326
327 if(ar9271_rx_status_error(rx_status->status))
328 continue;
329
330 void *strip_buffer = buffer + strip_length;
331
332 ieee80211_rx_handler(ar9271->ieee80211_dev,
333 strip_buffer,
334 payload_length);
335 }
336 }
337
338 free(buffer);
339
340 return EOK;
341}
342
343/**
344 * IEEE 802.11 handlers.
345 */
346
347static int ar9271_ieee80211_set_freq(ieee80211_dev_t *ieee80211_dev,
348 uint16_t freq)
349{
350 assert(ieee80211_dev);
351
352 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
353
354 wmi_send_command(ar9271->htc_device, WMI_DISABLE_INTR, NULL, 0, NULL);
355 wmi_send_command(ar9271->htc_device, WMI_DRAIN_TXQ_ALL, NULL, 0, NULL);
356 wmi_send_command(ar9271->htc_device, WMI_STOP_RECV, NULL, 0, NULL);
357
358 int rc = hw_freq_switch(ar9271, freq);
359 if(rc != EOK) {
360 usb_log_error("Failed to HW switch frequency.\n");
361 return rc;
362 }
363
364 wmi_send_command(ar9271->htc_device, WMI_START_RECV, NULL, 0, NULL);
365
366 rc = hw_rx_init(ar9271);
367 if(rc != EOK) {
368 usb_log_error("Failed to initialize RX.\n");
369 return rc;
370 }
371
372 uint16_t htc_mode = host2uint16_t_be(1);
373 wmi_send_command(ar9271->htc_device, WMI_SET_MODE,
374 (uint8_t *) &htc_mode, sizeof(htc_mode), NULL);
375 wmi_send_command(ar9271->htc_device, WMI_ENABLE_INTR, NULL, 0, NULL);
376
377 return EOK;
378}
379
380static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev,
381 bool connected)
382{
383 assert(ieee80211_dev);
384
385 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
386
387 if(connected) {
388 nic_address_t bssid;
389 ieee80211_query_bssid(ieee80211_dev, &bssid);
390
391 htc_sta_msg_t sta_msg;
392 memset(&sta_msg, 0, sizeof(htc_sta_msg_t));
393 sta_msg.is_vif_sta = 0;
394 sta_msg.max_ampdu =
395 host2uint16_t_be(1 << IEEE80211_MAX_AMPDU_FACTOR);
396 sta_msg.sta_index = 1;
397 sta_msg.vif_index = 0;
398 memcpy(&sta_msg.addr, bssid.address, ETH_ADDR);
399
400 wmi_send_command(ar9271->htc_device, WMI_NODE_CREATE,
401 (uint8_t *) &sta_msg, sizeof(sta_msg), NULL);
402
403 htc_rate_msg_t rate_msg;
404 memset(&rate_msg, 0, sizeof(htc_rate_msg_t));
405 rate_msg.sta_index = 1;
406 rate_msg.is_new = 1;
407 rate_msg.legacy_rates_count =
408 ARRAY_SIZE(ieee80211bg_data_rates);
409 memcpy(&rate_msg.legacy_rates,
410 ieee80211bg_data_rates,
411 ARRAY_SIZE(ieee80211bg_data_rates));
412
413 wmi_send_command(ar9271->htc_device, WMI_RC_RATE_UPDATE,
414 (uint8_t *) &rate_msg, sizeof(rate_msg), NULL);
415
416 hw_set_rx_filter(ar9271, true);
417 } else {
418 uint8_t station_id = 1;
419 wmi_send_command(ar9271->htc_device, WMI_NODE_REMOVE,
420 &station_id, sizeof(station_id), NULL);
421
422 hw_set_rx_filter(ar9271, false);
423 }
424
425 hw_set_bssid(ar9271);
426
427 return EOK;
428}
429
430static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev,
431 ieee80211_key_config_t *key_conf, bool insert)
432{
433 assert(ieee80211_dev);
434
435 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
436
437 if(insert) {
438 assert(key_conf);
439
440 uint32_t key[5];
441 uint32_t key_type;
442 uint32_t reg_ptr, mic_reg_ptr;
443 void *data_start;
444
445 nic_address_t bssid;
446 ieee80211_query_bssid(ieee80211_dev, &bssid);
447
448 switch(key_conf->suite) {
449 case IEEE80211_SECURITY_SUITE_WEP40:
450 key_type = AR9271_KEY_TABLE_TYPE_WEP40;
451 break;
452 case IEEE80211_SECURITY_SUITE_WEP104:
453 key_type = AR9271_KEY_TABLE_TYPE_WEP104;
454 break;
455 case IEEE80211_SECURITY_SUITE_TKIP:
456 key_type = AR9271_KEY_TABLE_TYPE_TKIP;
457 break;
458 case IEEE80211_SECURITY_SUITE_CCMP:
459 key_type = AR9271_KEY_TABLE_TYPE_CCMP;
460 break;
461 default:
462 key_type = -1;
463 }
464
465 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) {
466 reg_ptr = AR9271_KEY_TABLE_STA;
467 mic_reg_ptr = AR9271_KEY_TABLE_MIC_STA;
468 } else {
469 reg_ptr = AR9271_KEY_TABLE_GRP;
470 mic_reg_ptr = AR9271_KEY_TABLE_MIC_GRP;
471 }
472
473 data_start = (void *) key_conf->data;
474
475 key[0] = uint32_t_le2host(
476 *((uint32_t *) data_start));
477 key[1] = uint16_t_le2host(
478 *((uint16_t *) (data_start + 4)));
479 key[2] = uint32_t_le2host(
480 *((uint32_t *) (data_start + 6)));
481 key[3] = uint16_t_le2host(
482 *((uint16_t *) (data_start + 10)));
483 key[4] = uint32_t_le2host(
484 *((uint32_t *) (data_start + 12)));
485
486 if(key_conf->suite == IEEE80211_SECURITY_SUITE_WEP40 ||
487 key_conf->suite == IEEE80211_SECURITY_SUITE_WEP104) {
488 key[4] &= 0xFF;
489 }
490
491 wmi_reg_write(ar9271->htc_device, reg_ptr + 0, key[0]);
492 wmi_reg_write(ar9271->htc_device, reg_ptr + 4, key[1]);
493 wmi_reg_write(ar9271->htc_device, reg_ptr + 8, key[2]);
494 wmi_reg_write(ar9271->htc_device, reg_ptr + 12, key[3]);
495 wmi_reg_write(ar9271->htc_device, reg_ptr + 16, key[4]);
496 wmi_reg_write(ar9271->htc_device, reg_ptr + 20, key_type);
497
498 uint32_t macL, macH;
499 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) {
500 data_start = (void *) bssid.address;
501 macL = uint32_t_le2host(*((uint32_t *) data_start));
502 macH = uint16_t_le2host(*((uint16_t *)
503 (data_start + 4)));
504 } else {
505 macL = macH = 0;
506 }
507
508 macL >>= 1;
509 macL |= (macH & 1) << 31;
510 macH >>= 1;
511 macH |= 0x8000;
512
513 wmi_reg_write(ar9271->htc_device, reg_ptr + 24, macL);
514 wmi_reg_write(ar9271->htc_device, reg_ptr + 28, macH);
515
516 /* Setup MIC keys for TKIP. */
517 if(key_conf->suite == IEEE80211_SECURITY_SUITE_TKIP) {
518 uint32_t mic[5];
519 uint8_t *gen_mic =
520 data_start + IEEE80211_TKIP_RX_MIC_OFFSET;
521 uint8_t *tx_mic;
522 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP) {
523 tx_mic = gen_mic;
524 } else {
525 tx_mic = data_start +
526 IEEE80211_TKIP_TX_MIC_OFFSET;
527 }
528
529 mic[0] = uint32_t_le2host(
530 *((uint32_t *) gen_mic));
531 mic[1] = uint16_t_le2host(
532 *((uint16_t *) (tx_mic + 2))) & 0xFFFF;
533 mic[2] = uint32_t_le2host(
534 *((uint32_t *) (gen_mic + 4)));
535 mic[3] = uint16_t_le2host(
536 *((uint16_t *) tx_mic)) & 0xFFFF;
537 mic[4] = uint32_t_le2host(
538 *((uint32_t *) (tx_mic + 4)));
539
540 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 0,
541 mic[0]);
542 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 4,
543 mic[1]);
544 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 8,
545 mic[2]);
546 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 12,
547 mic[3]);
548 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 16,
549 mic[4]);
550 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 20,
551 AR9271_KEY_TABLE_TYPE_CLR);
552
553 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 24, 0);
554 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 28, 0);
555 }
556
557 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP)
558 ieee80211_setup_key_confirm(ieee80211_dev, true);
559 } else {
560 // TODO: Delete keys from device
561 ieee80211_setup_key_confirm(ieee80211_dev, false);
562 }
563
564 return EOK;
565}
566
567static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *ieee80211_dev,
568 void *buffer, size_t buffer_size)
569{
570 assert(ieee80211_dev);
571
572 size_t complete_size, offset;
573 void *complete_buffer;
574 int endpoint;
575
576 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
577
578 uint16_t frame_ctrl = *((uint16_t *) buffer);
579 if(ieee80211_is_data_frame(frame_ctrl)) {
580 offset = sizeof(htc_tx_data_header_t) +
581 sizeof(htc_frame_header_t);
582 complete_size = buffer_size + offset;
583 complete_buffer = malloc(complete_size);
584 memset(complete_buffer, 0, complete_size);
585
586 /*
587 * Because we handle just station mode yet, node ID and VIF ID
588 * are fixed.
589 */
590 htc_tx_data_header_t *data_header =
591 (htc_tx_data_header_t *)
592 (complete_buffer + sizeof(htc_frame_header_t));
593 /* TODO: Distinguish data type. */
594 data_header->data_type = HTC_DATA_NORMAL;
595 data_header->node_idx = 1;
596 data_header->vif_idx = 0;
597 /* TODO: There I should probably handle slot number. */
598 data_header->cookie = 0;
599
600 if(ieee80211_query_using_key(ieee80211_dev)) {
601 data_header->keyix = AR9271_STA_KEY_INDEX;
602 int sec_suite =
603 ieee80211_get_pairwise_security(ieee80211_dev);
604 switch(sec_suite) {
605 case IEEE80211_SECURITY_SUITE_WEP40:
606 case IEEE80211_SECURITY_SUITE_WEP104:
607 data_header->key_type =
608 AR9271_KEY_TYPE_WEP;
609 break;
610 case IEEE80211_SECURITY_SUITE_TKIP:
611 data_header->key_type =
612 AR9271_KEY_TYPE_TKIP;
613 break;
614 case IEEE80211_SECURITY_SUITE_CCMP:
615 data_header->key_type =
616 AR9271_KEY_TYPE_AES;
617 break;
618 }
619 } else {
620 data_header->key_type = 0;
621 data_header->keyix = 0xFF;
622 }
623
624 endpoint = ar9271->htc_device->endpoints.data_be_endpoint;
625 } else {
626 offset = sizeof(htc_tx_management_header_t) +
627 sizeof(htc_frame_header_t);
628 complete_size = buffer_size + offset;
629 complete_buffer = malloc(complete_size);
630 memset(complete_buffer, 0, complete_size);
631
632 /*
633 * Because we handle just station mode yet, node ID and VIF ID
634 * are fixed.
635 */
636 htc_tx_management_header_t *mgmt_header =
637 (htc_tx_management_header_t *)
638 (complete_buffer + sizeof(htc_frame_header_t));
639 mgmt_header->node_idx = 0;
640 mgmt_header->vif_idx = 0;
641 /* TODO: There I should probably handle slot number. */
642 mgmt_header->cookie = 0;
643 mgmt_header->keyix = 0xFF;
644
645 endpoint = ar9271->htc_device->endpoints.mgmt_endpoint;
646 }
647
648 /* Copy IEEE802.11 data to new allocated buffer with HTC headers. */
649 memcpy(complete_buffer + offset, buffer, buffer_size);
650
651 htc_send_data_message(ar9271->htc_device, complete_buffer,
652 complete_size, endpoint);
653
654 free(complete_buffer);
655
656 return EOK;
657}
658
659static int ar9271_ieee80211_start(ieee80211_dev_t *ieee80211_dev)
660{
661 assert(ieee80211_dev);
662
663 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
664
665 wmi_send_command(ar9271->htc_device, WMI_FLUSH_RECV, NULL, 0, NULL);
666
667 int rc = hw_reset(ar9271);
668 if(rc != EOK) {
669 usb_log_error("Failed to do HW reset.\n");
670 return rc;
671 }
672
673 uint16_t htc_mode = host2uint16_t_be(1);
674 wmi_send_command(ar9271->htc_device, WMI_SET_MODE,
675 (uint8_t *) &htc_mode, sizeof(htc_mode), NULL);
676 wmi_send_command(ar9271->htc_device, WMI_ATH_INIT, NULL, 0, NULL);
677 wmi_send_command(ar9271->htc_device, WMI_START_RECV, NULL, 0, NULL);
678 wmi_send_command(ar9271->htc_device, WMI_ENABLE_INTR, NULL, 0, NULL);
679
680 rc = hw_rx_init(ar9271);
681 if(rc != EOK) {
682 usb_log_error("Failed to initialize RX.\n");
683 return rc;
684 }
685
686 /* Send capability message to target. */
687 htc_cap_msg_t cap_msg;
688 cap_msg.ampdu_limit = host2uint32_t_be(0xFFFF);
689 cap_msg.ampdu_subframes = 0xFF;
690 cap_msg.enable_coex = 0;
691 cap_msg.tx_chainmask = 0x1;
692
693 wmi_send_command(ar9271->htc_device, WMI_TARGET_IC_UPDATE,
694 (uint8_t *) &cap_msg, sizeof(cap_msg), NULL);
695
696 rc = htc_init_new_vif(ar9271->htc_device);
697 if(rc != EOK) {
698 usb_log_error("Failed to initialize new VIF.\n");
699 return rc;
700 }
701
702 /* Add data polling fibril. */
703 fid_t fibril = fibril_create(ar9271_data_polling, ar9271);
704 if (fibril == 0) {
705 return ENOMEM;
706 }
707 fibril_add_ready(fibril);
708
709 ar9271->starting_up = false;
710 ieee80211_set_ready(ieee80211_dev, true);
711
712 usb_log_info("Device fully initialized.\n");
713
714 return EOK;
715}
716
717static int ar9271_init(ar9271_t *ar9271, usb_device_t *usb_device)
718{
719 ar9271->starting_up = true;
720 ar9271->usb_device = usb_device;
721
722 fibril_mutex_initialize(&ar9271->ar9271_lock);
723
724 ar9271->ath_device = calloc(1, sizeof(ath_t));
725 if (!ar9271->ath_device) {
726 usb_log_error("Failed to allocate memory for ath device "
727 "structure.\n");
728 return ENOMEM;
729 }
730
731 int rc = ath_usb_init(ar9271->ath_device, usb_device);
732 if(rc != EOK) {
733 free(ar9271->ath_device);
734 usb_log_error("Failed to initialize ath device.\n");
735 return rc;
736 }
737
738 /* IEEE 802.11 framework structure initialization. */
739 ar9271->ieee80211_dev = ieee80211_device_create();
740 if (!ar9271->ieee80211_dev) {
741 free(ar9271->ath_device);
742 usb_log_error("Failed to allocate memory for IEEE80211 device "
743 "structure.\n");
744 return ENOMEM;
745 }
746
747 rc = ieee80211_device_init(ar9271->ieee80211_dev, ar9271->ddf_dev);
748 if(rc != EOK) {
749 free(ar9271->ieee80211_dev);
750 free(ar9271->ath_device);
751 usb_log_error("Failed to initialize IEEE80211 device structure."
752 "\n");
753 return rc;
754 }
755
756 ieee80211_set_specific(ar9271->ieee80211_dev, ar9271);
757
758 /* HTC device structure initialization. */
759 ar9271->htc_device = calloc(1, sizeof(htc_device_t));
760 if(!ar9271->htc_device) {
761 free(ar9271->ieee80211_dev);
762 free(ar9271->ath_device);
763 usb_log_error("Failed to allocate memory for HTC device "
764 "structure.\n");
765 return ENOMEM;
766 }
767
768 rc = htc_device_init(ar9271->ath_device, ar9271->ieee80211_dev,
769 ar9271->htc_device);
770 if(rc != EOK) {
771 free(ar9271->htc_device);
772 free(ar9271->ieee80211_dev);
773 free(ar9271->ath_device);
774 usb_log_error("Failed to initialize HTC device structure.\n");
775 return rc;
776 }
777
778 return EOK;
779}
780
781/**
782 * Upload firmware to WiFi device.
783 *
784 * @param ar9271 AR9271 device structure
785 *
786 * @return EOK if succeed, negative error code otherwise
787 */
788static int ar9271_upload_fw(ar9271_t *ar9271)
789{
790 int rc;
791
792 usb_device_t *usb_device = ar9271->usb_device;
793
794 /* TODO: Set by maximum packet size in pipe. */
795 static const size_t MAX_TRANSFER_SIZE = 512;
796
797 /* Load FW from file. */
798 FILE *fw_file = fopen(FIRMWARE_FILENAME, "rb");
799 if (fw_file == NULL) {
800 usb_log_error("Failed opening file with firmware.\n");
801 return ENOENT;
802 }
803
804 fseek(fw_file, 0, SEEK_END);
805 uint64_t file_size = ftell(fw_file);
806 fseek(fw_file, 0, SEEK_SET);
807
808 void *fw_data = malloc(file_size);
809 if(fw_data == NULL) {
810 fclose(fw_file);
811 usb_log_error("Failed allocating memory for firmware.\n");
812 return ENOMEM;
813 }
814
815 fread(fw_data, file_size, 1, fw_file);
816 fclose(fw_file);
817
818 /* Upload FW to device. */
819 uint64_t remain_size = file_size;
820 uint32_t current_addr = AR9271_FW_ADDRESS;
821 uint8_t *current_data = fw_data;
822 uint8_t *buffer = malloc(MAX_TRANSFER_SIZE);
823 while(remain_size > 0) {
824 size_t chunk_size = min(remain_size, MAX_TRANSFER_SIZE);
825 memcpy(buffer, current_data, chunk_size);
826 rc = usb_control_request_set(&usb_device->ctrl_pipe,
827 USB_REQUEST_TYPE_VENDOR,
828 USB_REQUEST_RECIPIENT_DEVICE,
829 AR9271_FW_DOWNLOAD,
830 uint16_host2usb(current_addr >> 8),
831 0, buffer, chunk_size);
832 if(rc != EOK) {
833 free(fw_data);
834 free(buffer);
835 usb_log_error("Error while uploading firmware. "
836 "Error: %d\n", rc);
837 return rc;
838 }
839
840 remain_size -= chunk_size;
841 current_addr += chunk_size;
842 current_data += chunk_size;
843 }
844
845 free(fw_data);
846 free(buffer);
847
848 /* Send command that firmware is successfully uploaded.
849 * This should initiate creating confirmation message in
850 * device side buffer which we will check in htc_check_ready function.
851 */
852 rc = usb_control_request_set(&usb_device->ctrl_pipe,
853 USB_REQUEST_TYPE_VENDOR,
854 USB_REQUEST_RECIPIENT_DEVICE,
855 AR9271_FW_DOWNLOAD_COMP,
856 uint16_host2usb(AR9271_FW_OFFSET >> 8),
857 0, NULL, 0);
858
859 if(rc != EOK) {
860 usb_log_error("IO error when sending fw upload confirmation "
861 "message.\n");
862 return rc;
863 }
864
865 usb_log_info("Firmware uploaded successfully.\n");
866
867 /* Wait until firmware is ready - wait for 1 second to be sure. */
868 sleep(1);
869
870 return rc;
871}
872
873/** Create driver data structure.
874 *
875 * @param dev The device structure
876 *
877 * @return Intialized device data structure or NULL if error occured
878 */
879static ar9271_t *ar9271_create_dev_data(ddf_dev_t *dev)
880{
881 /* USB framework initialization. */
882 usb_device_t *usb_device = calloc(1, sizeof(usb_device_t));
883 if (usb_device == NULL) {
884 usb_log_error("USB device structure allocation failed.\n");
885 return NULL;
886 }
887
888 const char *err_msg = NULL;
889 int rc = usb_device_init(usb_device, dev, endpoints, &err_msg);
890 if(rc != EOK) {
891 free(usb_device);
892 usb_log_error("Failed to create USB device: %s, "
893 "ERR_NUM = %d\n", err_msg, rc);
894 return NULL;
895 }
896
897 /* AR9271 structure initialization. */
898 ar9271_t *ar9271 = calloc(1, sizeof(ar9271_t));
899 if (!ar9271) {
900 free(usb_device);
901 usb_log_error("Failed to allocate memory for device "
902 "structure.\n");
903 return NULL;
904 }
905
906 ar9271->ddf_dev = dev;
907
908 rc = ar9271_init(ar9271, usb_device);
909 if(rc != EOK) {
910 free(ar9271);
911 free(usb_device);
912 usb_log_error("Failed to initialize AR9271 structure: %d\n",
913 rc);
914 return NULL;
915 }
916
917 return ar9271;
918}
919
920/** Clean up the ar9271 device structure.
921 *
922 * @param dev The device structure.
923 */
924static void ar9271_delete_dev_data(ar9271_t *ar9271)
925{
926 assert(ar9271);
927
928 // TODO
929}
930
931/** Probe and initialize the newly added device.
932 *
933 * @param dev The device structure.
934 *
935 * @return EOK if succeed, negative error code otherwise
936 */
937static int ar9271_add_device(ddf_dev_t *dev)
938{
939 assert(dev);
940
941 /* Allocate driver data for the device. */
942 ar9271_t *ar9271 = ar9271_create_dev_data(dev);
943 if (ar9271 == NULL) {
944 usb_log_error("Unable to allocate device softstate.\n");
945 return ENOMEM;
946 }
947
948 usb_log_info("HelenOS AR9271 device initialized.\n");
949
950 /* Upload AR9271 firmware. */
951 ar9271_upload_fw(ar9271);
952
953 /* Initialize AR9271 HTC services. */
954 int rc = htc_init(ar9271->htc_device);
955 if(rc != EOK) {
956 ar9271_delete_dev_data(ar9271);
957 usb_log_error("HTC initialization failed.\n");
958 return rc;
959 }
960
961 /* Initialize AR9271 HW. */
962 rc = hw_init(ar9271);
963 if(rc != EOK) {
964 ar9271_delete_dev_data(ar9271);
965 usb_log_error("HW initialization failed.\n");
966 return rc;
967 }
968
969 /* Initialize AR9271 IEEE 802.11 framework. */
970 rc = ieee80211_init(ar9271->ieee80211_dev, &ar9271_ieee80211_ops,
971 &ar9271_ieee80211_iface, &ar9271_ieee80211_nic_iface,
972 &ar9271_ieee80211_dev_ops);
973 if(rc != EOK) {
974 ar9271_delete_dev_data(ar9271);
975 usb_log_error("Failed to initialize IEEE80211 framework.\n");
976 return rc;
977 }
978
979 nic_set_filtering_change_handlers(nic_get_from_ddf_dev(dev),
980 ar9271_on_unicast_mode_change, ar9271_on_multicast_mode_change,
981 ar9271_on_broadcast_mode_change, NULL, NULL);
982
983 usb_log_info("HelenOS AR9271 added device.\n");
984
985 return EOK;
986}
987
988int main(void)
989{
990 log_init(NAME);
991
992 if (nic_driver_init(NAME) != EOK)
993 return 1;
994
995 usb_log_info("HelenOS AR9271 driver started.\n");
996
997 return ddf_driver_main(&ar9271_driver);
998}
Note: See TracBrowser for help on using the repository browser.