source: mainline/uspace/drv/nic/ar9271/ar9271.c@ 09044cb

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

Fixed parsing RSN information, fixed inserting GTK of various index to device

  • Property mode set to 100644
File size: 25.5 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 uint8_t key_id =
466 (key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) ?
467 AR9271_STA_KEY_INDEX : key_conf->id;
468
469 reg_ptr = AR9271_KEY_TABLE(key_id);
470 mic_reg_ptr = AR9271_KEY_TABLE(key_id + 64);
471 data_start = (void *) key_conf->data;
472
473 key[0] = uint32_t_le2host(
474 *((uint32_t *) data_start));
475 key[1] = uint16_t_le2host(
476 *((uint16_t *) (data_start + 4)));
477 key[2] = uint32_t_le2host(
478 *((uint32_t *) (data_start + 6)));
479 key[3] = uint16_t_le2host(
480 *((uint16_t *) (data_start + 10)));
481 key[4] = uint32_t_le2host(
482 *((uint32_t *) (data_start + 12)));
483
484 if(key_conf->suite == IEEE80211_SECURITY_SUITE_WEP40 ||
485 key_conf->suite == IEEE80211_SECURITY_SUITE_WEP104) {
486 key[4] &= 0xFF;
487 }
488
489 wmi_reg_write(ar9271->htc_device, reg_ptr + 0, key[0]);
490 wmi_reg_write(ar9271->htc_device, reg_ptr + 4, key[1]);
491 wmi_reg_write(ar9271->htc_device, reg_ptr + 8, key[2]);
492 wmi_reg_write(ar9271->htc_device, reg_ptr + 12, key[3]);
493 wmi_reg_write(ar9271->htc_device, reg_ptr + 16, key[4]);
494 wmi_reg_write(ar9271->htc_device, reg_ptr + 20, key_type);
495
496 uint32_t macL, macH;
497 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) {
498 data_start = (void *) bssid.address;
499 macL = uint32_t_le2host(*((uint32_t *) data_start));
500 macH = uint16_t_le2host(*((uint16_t *)
501 (data_start + 4)));
502 } else {
503 macL = macH = 0;
504 }
505
506 macL >>= 1;
507 macL |= (macH & 1) << 31;
508 macH >>= 1;
509 macH |= 0x8000;
510
511 wmi_reg_write(ar9271->htc_device, reg_ptr + 24, macL);
512 wmi_reg_write(ar9271->htc_device, reg_ptr + 28, macH);
513
514 /* Setup MIC keys for TKIP. */
515 if(key_conf->suite == IEEE80211_SECURITY_SUITE_TKIP) {
516 uint32_t mic[5];
517 uint8_t *gen_mic =
518 data_start + IEEE80211_TKIP_RX_MIC_OFFSET;
519 uint8_t *tx_mic;
520 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP) {
521 tx_mic = gen_mic;
522 } else {
523 tx_mic = data_start +
524 IEEE80211_TKIP_TX_MIC_OFFSET;
525 }
526
527 mic[0] = uint32_t_le2host(
528 *((uint32_t *) gen_mic));
529 mic[1] = uint16_t_le2host(
530 *((uint16_t *) (tx_mic + 2))) & 0xFFFF;
531 mic[2] = uint32_t_le2host(
532 *((uint32_t *) (gen_mic + 4)));
533 mic[3] = uint16_t_le2host(
534 *((uint16_t *) tx_mic)) & 0xFFFF;
535 mic[4] = uint32_t_le2host(
536 *((uint32_t *) (tx_mic + 4)));
537
538 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 0,
539 mic[0]);
540 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 4,
541 mic[1]);
542 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 8,
543 mic[2]);
544 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 12,
545 mic[3]);
546 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 16,
547 mic[4]);
548 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 20,
549 AR9271_KEY_TABLE_TYPE_CLR);
550
551 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 24, 0);
552 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 28, 0);
553 }
554
555 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP)
556 ieee80211_setup_key_confirm(ieee80211_dev, true);
557 } else {
558 /* TODO: Delete keys from device */
559 ieee80211_setup_key_confirm(ieee80211_dev, false);
560 }
561
562 return EOK;
563}
564
565static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *ieee80211_dev,
566 void *buffer, size_t buffer_size)
567{
568 assert(ieee80211_dev);
569
570 size_t complete_size, offset;
571 void *complete_buffer;
572 int endpoint;
573
574 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
575
576 uint16_t frame_ctrl = *((uint16_t *) buffer);
577 if(ieee80211_is_data_frame(frame_ctrl)) {
578 offset = sizeof(htc_tx_data_header_t) +
579 sizeof(htc_frame_header_t);
580 complete_size = buffer_size + offset;
581 complete_buffer = malloc(complete_size);
582 memset(complete_buffer, 0, complete_size);
583
584 /*
585 * Because we handle just station mode yet, node ID and VIF ID
586 * are fixed.
587 */
588 htc_tx_data_header_t *data_header =
589 (htc_tx_data_header_t *)
590 (complete_buffer + sizeof(htc_frame_header_t));
591 data_header->data_type = HTC_DATA_NORMAL;
592 data_header->node_idx = 1;
593 data_header->vif_idx = 0;
594 data_header->cookie = 0;
595
596 if(ieee80211_query_using_key(ieee80211_dev)) {
597 data_header->keyix = AR9271_STA_KEY_INDEX;
598 int sec_suite =
599 ieee80211_get_pairwise_security(ieee80211_dev);
600 switch(sec_suite) {
601 case IEEE80211_SECURITY_SUITE_WEP40:
602 case IEEE80211_SECURITY_SUITE_WEP104:
603 data_header->key_type =
604 AR9271_KEY_TYPE_WEP;
605 break;
606 case IEEE80211_SECURITY_SUITE_TKIP:
607 data_header->key_type =
608 AR9271_KEY_TYPE_TKIP;
609 break;
610 case IEEE80211_SECURITY_SUITE_CCMP:
611 data_header->key_type =
612 AR9271_KEY_TYPE_AES;
613 break;
614 }
615 } else {
616 data_header->key_type = 0;
617 data_header->keyix = 0xFF;
618 }
619
620 endpoint = ar9271->htc_device->endpoints.data_be_endpoint;
621 } else {
622 offset = sizeof(htc_tx_management_header_t) +
623 sizeof(htc_frame_header_t);
624 complete_size = buffer_size + offset;
625 complete_buffer = malloc(complete_size);
626 memset(complete_buffer, 0, complete_size);
627
628 /*
629 * Because we handle just station mode yet, node ID and VIF ID
630 * are fixed.
631 */
632 htc_tx_management_header_t *mgmt_header =
633 (htc_tx_management_header_t *)
634 (complete_buffer + sizeof(htc_frame_header_t));
635 mgmt_header->node_idx = 0;
636 mgmt_header->vif_idx = 0;
637 mgmt_header->cookie = 0;
638 mgmt_header->keyix = 0xFF;
639
640 endpoint = ar9271->htc_device->endpoints.mgmt_endpoint;
641 }
642
643 /* Copy IEEE802.11 data to new allocated buffer with HTC headers. */
644 memcpy(complete_buffer + offset, buffer, buffer_size);
645
646 htc_send_data_message(ar9271->htc_device, complete_buffer,
647 complete_size, endpoint);
648
649 free(complete_buffer);
650
651 return EOK;
652}
653
654static int ar9271_ieee80211_start(ieee80211_dev_t *ieee80211_dev)
655{
656 assert(ieee80211_dev);
657
658 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
659
660 wmi_send_command(ar9271->htc_device, WMI_FLUSH_RECV, NULL, 0, NULL);
661
662 int rc = hw_reset(ar9271);
663 if(rc != EOK) {
664 usb_log_error("Failed to do HW reset.\n");
665 return rc;
666 }
667
668 uint16_t htc_mode = host2uint16_t_be(1);
669 wmi_send_command(ar9271->htc_device, WMI_SET_MODE,
670 (uint8_t *) &htc_mode, sizeof(htc_mode), NULL);
671 wmi_send_command(ar9271->htc_device, WMI_ATH_INIT, NULL, 0, NULL);
672 wmi_send_command(ar9271->htc_device, WMI_START_RECV, NULL, 0, NULL);
673 wmi_send_command(ar9271->htc_device, WMI_ENABLE_INTR, NULL, 0, NULL);
674
675 rc = hw_rx_init(ar9271);
676 if(rc != EOK) {
677 usb_log_error("Failed to initialize RX.\n");
678 return rc;
679 }
680
681 /* Send capability message to target. */
682 htc_cap_msg_t cap_msg;
683 cap_msg.ampdu_limit = host2uint32_t_be(0xFFFF);
684 cap_msg.ampdu_subframes = 0xFF;
685 cap_msg.enable_coex = 0;
686 cap_msg.tx_chainmask = 0x1;
687
688 wmi_send_command(ar9271->htc_device, WMI_TARGET_IC_UPDATE,
689 (uint8_t *) &cap_msg, sizeof(cap_msg), NULL);
690
691 rc = htc_init_new_vif(ar9271->htc_device);
692 if(rc != EOK) {
693 usb_log_error("Failed to initialize new VIF.\n");
694 return rc;
695 }
696
697 /* Add data polling fibril. */
698 fid_t fibril = fibril_create(ar9271_data_polling, ar9271);
699 if (fibril == 0) {
700 return ENOMEM;
701 }
702 fibril_add_ready(fibril);
703
704 ar9271->starting_up = false;
705 ieee80211_set_ready(ieee80211_dev, true);
706
707 usb_log_info("Device fully initialized.\n");
708
709 return EOK;
710}
711
712static int ar9271_init(ar9271_t *ar9271, usb_device_t *usb_device)
713{
714 ar9271->starting_up = true;
715 ar9271->usb_device = usb_device;
716
717 fibril_mutex_initialize(&ar9271->ar9271_lock);
718
719 ar9271->ath_device = calloc(1, sizeof(ath_t));
720 if (!ar9271->ath_device) {
721 usb_log_error("Failed to allocate memory for ath device "
722 "structure.\n");
723 return ENOMEM;
724 }
725
726 int rc = ath_usb_init(ar9271->ath_device, usb_device);
727 if(rc != EOK) {
728 free(ar9271->ath_device);
729 usb_log_error("Failed to initialize ath device.\n");
730 return rc;
731 }
732
733 /* IEEE 802.11 framework structure initialization. */
734 ar9271->ieee80211_dev = ieee80211_device_create();
735 if (!ar9271->ieee80211_dev) {
736 free(ar9271->ath_device);
737 usb_log_error("Failed to allocate memory for IEEE80211 device "
738 "structure.\n");
739 return ENOMEM;
740 }
741
742 rc = ieee80211_device_init(ar9271->ieee80211_dev, ar9271->ddf_dev);
743 if(rc != EOK) {
744 free(ar9271->ieee80211_dev);
745 free(ar9271->ath_device);
746 usb_log_error("Failed to initialize IEEE80211 device structure."
747 "\n");
748 return rc;
749 }
750
751 ieee80211_set_specific(ar9271->ieee80211_dev, ar9271);
752
753 /* HTC device structure initialization. */
754 ar9271->htc_device = calloc(1, sizeof(htc_device_t));
755 if(!ar9271->htc_device) {
756 free(ar9271->ieee80211_dev);
757 free(ar9271->ath_device);
758 usb_log_error("Failed to allocate memory for HTC device "
759 "structure.\n");
760 return ENOMEM;
761 }
762
763 rc = htc_device_init(ar9271->ath_device, ar9271->ieee80211_dev,
764 ar9271->htc_device);
765 if(rc != EOK) {
766 free(ar9271->htc_device);
767 free(ar9271->ieee80211_dev);
768 free(ar9271->ath_device);
769 usb_log_error("Failed to initialize HTC device structure.\n");
770 return rc;
771 }
772
773 return EOK;
774}
775
776/**
777 * Upload firmware to WiFi device.
778 *
779 * @param ar9271 AR9271 device structure
780 *
781 * @return EOK if succeed, negative error code otherwise
782 */
783static int ar9271_upload_fw(ar9271_t *ar9271)
784{
785 int rc;
786
787 usb_device_t *usb_device = ar9271->usb_device;
788
789 /* TODO: Set by maximum packet size in pipe. */
790 static const size_t MAX_TRANSFER_SIZE = 512;
791
792 /* Load FW from file. */
793 FILE *fw_file = fopen(FIRMWARE_FILENAME, "rb");
794 if (fw_file == NULL) {
795 usb_log_error("Failed opening file with firmware.\n");
796 return ENOENT;
797 }
798
799 fseek(fw_file, 0, SEEK_END);
800 uint64_t file_size = ftell(fw_file);
801 fseek(fw_file, 0, SEEK_SET);
802
803 void *fw_data = malloc(file_size);
804 if(fw_data == NULL) {
805 fclose(fw_file);
806 usb_log_error("Failed allocating memory for firmware.\n");
807 return ENOMEM;
808 }
809
810 fread(fw_data, file_size, 1, fw_file);
811 fclose(fw_file);
812
813 /* Upload FW to device. */
814 uint64_t remain_size = file_size;
815 uint32_t current_addr = AR9271_FW_ADDRESS;
816 uint8_t *current_data = fw_data;
817 uint8_t *buffer = malloc(MAX_TRANSFER_SIZE);
818 while(remain_size > 0) {
819 size_t chunk_size = min(remain_size, MAX_TRANSFER_SIZE);
820 memcpy(buffer, current_data, chunk_size);
821 rc = usb_control_request_set(&usb_device->ctrl_pipe,
822 USB_REQUEST_TYPE_VENDOR,
823 USB_REQUEST_RECIPIENT_DEVICE,
824 AR9271_FW_DOWNLOAD,
825 uint16_host2usb(current_addr >> 8),
826 0, buffer, chunk_size);
827 if(rc != EOK) {
828 free(fw_data);
829 free(buffer);
830 usb_log_error("Error while uploading firmware. "
831 "Error: %d\n", rc);
832 return rc;
833 }
834
835 remain_size -= chunk_size;
836 current_addr += chunk_size;
837 current_data += chunk_size;
838 }
839
840 free(fw_data);
841 free(buffer);
842
843 /* Send command that firmware is successfully uploaded.
844 * This should initiate creating confirmation message in
845 * device side buffer which we will check in htc_check_ready function.
846 */
847 rc = usb_control_request_set(&usb_device->ctrl_pipe,
848 USB_REQUEST_TYPE_VENDOR,
849 USB_REQUEST_RECIPIENT_DEVICE,
850 AR9271_FW_DOWNLOAD_COMP,
851 uint16_host2usb(AR9271_FW_OFFSET >> 8),
852 0, NULL, 0);
853
854 if(rc != EOK) {
855 usb_log_error("IO error when sending fw upload confirmation "
856 "message.\n");
857 return rc;
858 }
859
860 usb_log_info("Firmware uploaded successfully.\n");
861
862 /* Wait until firmware is ready - wait for 1 second to be sure. */
863 sleep(1);
864
865 return rc;
866}
867
868/** Create driver data structure.
869 *
870 * @param dev The device structure
871 *
872 * @return Intialized device data structure or NULL if error occured
873 */
874static ar9271_t *ar9271_create_dev_data(ddf_dev_t *dev)
875{
876 /* USB framework initialization. */
877 usb_device_t *usb_device = calloc(1, sizeof(usb_device_t));
878 if (usb_device == NULL) {
879 usb_log_error("USB device structure allocation failed.\n");
880 return NULL;
881 }
882
883 const char *err_msg = NULL;
884 int rc = usb_device_init(usb_device, dev, endpoints, &err_msg);
885 if(rc != EOK) {
886 free(usb_device);
887 usb_log_error("Failed to create USB device: %s, "
888 "ERR_NUM = %d\n", err_msg, rc);
889 return NULL;
890 }
891
892 /* AR9271 structure initialization. */
893 ar9271_t *ar9271 = calloc(1, sizeof(ar9271_t));
894 if (!ar9271) {
895 free(usb_device);
896 usb_log_error("Failed to allocate memory for device "
897 "structure.\n");
898 return NULL;
899 }
900
901 ar9271->ddf_dev = dev;
902
903 rc = ar9271_init(ar9271, usb_device);
904 if(rc != EOK) {
905 free(ar9271);
906 free(usb_device);
907 usb_log_error("Failed to initialize AR9271 structure: %d\n",
908 rc);
909 return NULL;
910 }
911
912 return ar9271;
913}
914
915/** Clean up the ar9271 device structure.
916 *
917 * @param dev The device structure.
918 */
919static void ar9271_delete_dev_data(ar9271_t *ar9271)
920{
921 assert(ar9271);
922
923 // TODO
924}
925
926/** Probe and initialize the newly added device.
927 *
928 * @param dev The device structure.
929 *
930 * @return EOK if succeed, negative error code otherwise
931 */
932static int ar9271_add_device(ddf_dev_t *dev)
933{
934 assert(dev);
935
936 /* Allocate driver data for the device. */
937 ar9271_t *ar9271 = ar9271_create_dev_data(dev);
938 if (ar9271 == NULL) {
939 usb_log_error("Unable to allocate device softstate.\n");
940 return ENOMEM;
941 }
942
943 usb_log_info("HelenOS AR9271 device initialized.\n");
944
945 /* Upload AR9271 firmware. */
946 ar9271_upload_fw(ar9271);
947
948 /* Initialize AR9271 HTC services. */
949 int rc = htc_init(ar9271->htc_device);
950 if(rc != EOK) {
951 ar9271_delete_dev_data(ar9271);
952 usb_log_error("HTC initialization failed.\n");
953 return rc;
954 }
955
956 /* Initialize AR9271 HW. */
957 rc = hw_init(ar9271);
958 if(rc != EOK) {
959 ar9271_delete_dev_data(ar9271);
960 usb_log_error("HW initialization failed.\n");
961 return rc;
962 }
963
964 /* Initialize AR9271 IEEE 802.11 framework. */
965 rc = ieee80211_init(ar9271->ieee80211_dev, &ar9271_ieee80211_ops,
966 &ar9271_ieee80211_iface, &ar9271_ieee80211_nic_iface,
967 &ar9271_ieee80211_dev_ops);
968 if(rc != EOK) {
969 ar9271_delete_dev_data(ar9271);
970 usb_log_error("Failed to initialize IEEE80211 framework.\n");
971 return rc;
972 }
973
974 nic_set_filtering_change_handlers(nic_get_from_ddf_dev(dev),
975 ar9271_on_unicast_mode_change, ar9271_on_multicast_mode_change,
976 ar9271_on_broadcast_mode_change, NULL, NULL);
977
978 usb_log_info("HelenOS AR9271 added device.\n");
979
980 return EOK;
981}
982
983int main(void)
984{
985 log_init(NAME);
986
987 if (nic_driver_init(NAME) != EOK)
988 return 1;
989
990 usb_log_info("HelenOS AR9271 driver started.\n");
991
992 return ddf_driver_main(&ar9271_driver);
993}
Note: See TracBrowser for help on using the repository browser.