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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ee0ffa6 was b3c39690, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

usb: remove misleading usb_device_get_mapped_ep

Even though this method may seem very convenient to use, it's actually
wrong. The devices are usually not required to have strict endpoint
numbers. That's why the mapping mechanism exists. Therefore, it's just
not possible to rely on fixed endpoint mapping.

There could be similar method, that would take the transfer type and
direction, but it's much better to ask for the complete mapping then.

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