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

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

Scanning whole 2.4GHz spectrum, created supplicant for managing connection between device STA and AP, finished association process between STA and AP, handling 4way handshake protocol used for key management, written needed cryptographic algorithms (AES, SHA1, HMAC, PBKDF2) for CCMP protocol, data communication on OPEN/CCMP networks.

  • Property mode set to 100644
File size: 15.1 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 htc.c
30 *
31 * Implementation of Atheros HTC communication.
32 *
33 */
34
35#include <usb/debug.h>
36#include <byteorder.h>
37#include <errno.h>
38
39#include "wmi.h"
40#include "htc.h"
41#include "nic/nic.h"
42#include "ar9271.h"
43
44/**
45 * HTC download pipes mapping.
46 *
47 * @param service_id Identification of WMI service.
48 *
49 * @return Number of pipe used for this service.
50 */
51static inline uint8_t wmi_service_to_download_pipe(wmi_services_t service_id)
52{
53 return (service_id == WMI_CONTROL_SERVICE) ? 3 : 2;
54}
55
56/**
57 * HTC upload pipes mapping.
58 *
59 * @param service_id Identification of WMI service.
60 *
61 * @return Number of pipe used for this service.
62 */
63static inline uint8_t wmi_service_to_upload_pipe(wmi_services_t service_id)
64{
65 return (service_id == WMI_CONTROL_SERVICE) ? 4 : 1;
66}
67
68int htc_init_new_vif(htc_device_t *htc_device)
69{
70 htc_vif_msg_t vif_msg;
71 htc_sta_msg_t sta_msg;
72
73 memset(&vif_msg, 0, sizeof(htc_vif_msg_t));
74 memset(&sta_msg, 0, sizeof(htc_sta_msg_t));
75
76 nic_address_t addr;
77 nic_t *nic =
78 nic_get_from_ddf_dev(
79 ieee80211_get_ddf_dev(htc_device->ieee80211_dev)
80 );
81 nic_query_address(nic, &addr);
82
83 memcpy(&vif_msg.addr, &addr.address, ETH_ADDR);
84 memcpy(&sta_msg.addr, &addr.address, ETH_ADDR);
85
86 ieee80211_operating_mode_t op_mode =
87 ieee80211_query_current_op_mode(htc_device->ieee80211_dev);
88
89 switch(op_mode) {
90 case IEEE80211_OPMODE_ADHOC:
91 vif_msg.op_mode = HTC_OPMODE_ADHOC;
92 break;
93 case IEEE80211_OPMODE_AP:
94 vif_msg.op_mode = HTC_OPMODE_AP;
95 break;
96 case IEEE80211_OPMODE_MESH:
97 vif_msg.op_mode = HTC_OPMODE_MESH;
98 break;
99 case IEEE80211_OPMODE_STATION:
100 vif_msg.op_mode = HTC_OPMODE_STATION;
101 break;
102 }
103
104 vif_msg.index = 0;
105 vif_msg.rts_thres = host2uint16_t_be(HTC_RTS_THRESHOLD);
106
107 wmi_send_command(htc_device, WMI_VAP_CREATE, (uint8_t *) &vif_msg,
108 sizeof(vif_msg), NULL);
109
110 sta_msg.is_vif_sta = 1;
111 sta_msg.max_ampdu = host2uint16_t_be(0xFFFF);
112 sta_msg.sta_index = 0;
113 sta_msg.vif_index = 0;
114
115 wmi_send_command(htc_device, WMI_NODE_CREATE, (uint8_t *) &sta_msg,
116 sizeof(sta_msg), NULL);
117
118 /* Write first 4 bytes of MAC address. */
119 uint32_t id0;
120 memcpy(&id0, &addr.address, 4);
121 id0 = host2uint32_t_le(id0);
122 wmi_reg_write(htc_device, AR9271_STATION_ID0, id0);
123
124 /* Write last 2 bytes of MAC address (and preserve existing data). */
125 uint32_t id1;
126 wmi_reg_read(htc_device, AR9271_STATION_ID1, &id1);
127
128 uint16_t id1_addr;
129 memcpy(&id1_addr, &addr.address[4], 2);
130 id1 = (id1 & ~AR9271_STATION_ID1_MASK) | host2uint16_t_le(id1_addr);
131 wmi_reg_write(htc_device, AR9271_STATION_ID1, id1);
132
133 return EOK;
134}
135
136static void htc_config_frame_header(htc_frame_header_t *header,
137 size_t buffer_size, uint8_t endpoint_id)
138{
139 memset(header, 0, sizeof(htc_frame_header_t));
140
141 header->endpoint_id = endpoint_id;
142 header->payload_length =
143 host2uint16_t_be(buffer_size - sizeof(htc_frame_header_t));
144}
145
146/**
147 * Send control HTC message to USB device.
148 *
149 * @param htc_device HTC device structure.
150 * @param buffer Buffer with data to be sent to USB device (without HTC frame
151 * header).
152 * @param buffer_size Size of buffer (including HTC frame header).
153 * @param endpoint_id Destination endpoint.
154 *
155 * @return EOK if succeed, negative error code otherwise.
156 */
157int htc_send_control_message(htc_device_t *htc_device, void *buffer,
158 size_t buffer_size, uint8_t endpoint_id)
159{
160 htc_config_frame_header((htc_frame_header_t *) buffer, buffer_size,
161 endpoint_id);
162
163 ath_t *ath_device = htc_device->ath_device;
164
165 return ath_device->ops->send_ctrl_message(ath_device, buffer,
166 buffer_size);
167}
168
169/**
170 * Send data HTC message to USB device.
171 *
172 * @param htc_device HTC device structure.
173 * @param buffer Buffer with data to be sent to USB device (without HTC frame
174 * header).
175 * @param buffer_size Size of buffer (including HTC frame header).
176 * @param endpoint_id Destination endpoint.
177 *
178 * @return EOK if succeed, negative error code otherwise.
179 */
180int htc_send_data_message(htc_device_t *htc_device, void *buffer,
181 size_t buffer_size, uint8_t endpoint_id)
182{
183 htc_config_frame_header((htc_frame_header_t *) buffer, buffer_size,
184 endpoint_id);
185
186 ath_t *ath_device = htc_device->ath_device;
187
188 return ath_device->ops->send_data_message(ath_device, buffer,
189 buffer_size);
190}
191
192/**
193 * Read HTC data message from USB device.
194 *
195 * @param htc_device HTC device structure.
196 * @param buffer Buffer where data from USB device will be stored.
197 * @param buffer_size Size of buffer.
198 * @param transferred_size Real size of read data.
199 *
200 * @return EOK if succeed, negative error code otherwise.
201 */
202int htc_read_data_message(htc_device_t *htc_device, void *buffer,
203 size_t buffer_size, size_t *transferred_size)
204{
205 ath_t *ath_device = htc_device->ath_device;
206
207 return ath_device->ops->read_data_message(ath_device, buffer,
208 buffer_size, transferred_size);
209}
210
211/**
212 * Read HTC control message from USB device.
213 *
214 * @param htc_device HTC device structure.
215 * @param buffer Buffer where data from USB device will be stored.
216 * @param buffer_size Size of buffer.
217 * @param transferred_size Real size of read data.
218 *
219 * @return EOK if succeed, negative error code otherwise.
220 */
221int htc_read_control_message(htc_device_t *htc_device, void *buffer,
222 size_t buffer_size, size_t *transferred_size)
223{
224 ath_t *ath_device = htc_device->ath_device;
225
226 return ath_device->ops->read_ctrl_message(ath_device, buffer,
227 buffer_size, transferred_size);
228}
229
230/**
231 * Initialize HTC service.
232 *
233 * @param htc_device HTC device structure.
234 * @param service_id Identification of WMI service.
235 * @param response_endpoint_no HTC endpoint to be used for this service.
236 *
237 * @return EOK if succeed, EINVAL when failed to connect service,
238 * negative error code otherwise.
239 */
240static int htc_connect_service(htc_device_t *htc_device,
241 wmi_services_t service_id, int *response_endpoint_no)
242{
243 size_t buffer_size = sizeof(htc_frame_header_t) +
244 sizeof(htc_service_msg_t);
245 void *buffer = malloc(buffer_size);
246 memset(buffer, 0, buffer_size);
247
248 /* Fill service message structure. */
249 htc_service_msg_t *service_message = (htc_service_msg_t *)
250 ((void *) buffer + sizeof(htc_frame_header_t));
251 service_message->service_id =
252 host2uint16_t_be(service_id);
253 service_message->message_id =
254 host2uint16_t_be(HTC_MESSAGE_CONNECT_SERVICE);
255 service_message->download_pipe_id =
256 wmi_service_to_download_pipe(service_id);
257 service_message->upload_pipe_id =
258 wmi_service_to_upload_pipe(service_id);
259 service_message->connection_flags = 0;
260
261 /* Send HTC message. */
262 int rc = htc_send_control_message(htc_device, buffer, buffer_size,
263 htc_device->endpoints.ctrl_endpoint);
264 if(rc != EOK) {
265 free(buffer);
266 usb_log_error("Failed to send HTC message. Error: %d\n", rc);
267 return rc;
268 }
269
270 free(buffer);
271
272 buffer_size = htc_device->ath_device->ctrl_response_length;
273 buffer = malloc(buffer_size);
274
275 /* Read response from device. */
276 rc = htc_read_control_message(htc_device, buffer, buffer_size, NULL);
277 if(rc != EOK) {
278 free(buffer);
279 usb_log_error("Failed to receive HTC service connect response. "
280 "Error: %d\n", rc);
281 return rc;
282 }
283
284 htc_service_resp_msg_t *response_message = (htc_service_resp_msg_t *)
285 ((void *) buffer + sizeof(htc_frame_header_t));
286
287 /* If service was successfully connected, write down HTC endpoint number
288 * that will be used for communication. */
289 if(response_message->status == HTC_SERVICE_SUCCESS) {
290 *response_endpoint_no = response_message->endpoint_id;
291 rc = EOK;
292 } else {
293 usb_log_error("Failed to connect HTC service. "
294 "Message status: %d\n", response_message->status);
295 rc = EINVAL;
296 }
297
298 free(buffer);
299
300 return rc;
301}
302
303/**
304 * HTC credits initialization message.
305 *
306 * @param htc_device HTC device structure.
307 *
308 * @return EOK if succeed, negative error code otherwise.
309 */
310static int htc_config_credits(htc_device_t *htc_device)
311{
312 size_t buffer_size = sizeof(htc_frame_header_t) +
313 sizeof(htc_config_msg_t);
314 void *buffer = malloc(buffer_size);
315 htc_config_msg_t *config_message = (htc_config_msg_t *)
316 ((void *) buffer + sizeof(htc_frame_header_t));
317
318 config_message->message_id =
319 host2uint16_t_be(HTC_MESSAGE_CONFIG);
320 /* Magic number to initialize device. */
321 config_message->credits = 33;
322 config_message->pipe_id = 1;
323
324 /* Send HTC message. */
325 int rc = htc_send_control_message(htc_device, buffer, buffer_size,
326 htc_device->endpoints.ctrl_endpoint);
327 if(rc != EOK) {
328 free(buffer);
329 usb_log_error("Failed to send HTC config message. "
330 "Error: %d\n", rc);
331 return rc;
332 }
333
334 free(buffer);
335
336 buffer_size = htc_device->ath_device->ctrl_response_length;
337 buffer = malloc(buffer_size);
338
339 /* Check response from device. */
340 rc = htc_read_control_message(htc_device, buffer, buffer_size, NULL);
341 if(rc != EOK) {
342 usb_log_error("Failed to receive HTC config response message. "
343 "Error: %d\n", rc);
344 }
345
346 free(buffer);
347
348 return rc;
349}
350
351/**
352 * HTC setup complete confirmation message.
353 *
354 * @param htc_device HTC device structure.
355 *
356 * @return EOK if succeed, negative error code otherwise.
357 */
358static int htc_complete_setup(htc_device_t *htc_device)
359{
360 size_t buffer_size = sizeof(htc_frame_header_t) +
361 sizeof(htc_setup_complete_msg_t);
362 void *buffer = malloc(buffer_size);
363 htc_setup_complete_msg_t *complete_message =
364 (htc_setup_complete_msg_t *)
365 ((void *) buffer + sizeof(htc_frame_header_t));
366
367 complete_message->message_id =
368 host2uint16_t_be(HTC_MESSAGE_SETUP_COMPLETE);
369
370 /* Send HTC message. */
371 int rc = htc_send_control_message(htc_device, buffer, buffer_size,
372 htc_device->endpoints.ctrl_endpoint);
373 if(rc != EOK) {
374 usb_log_error("Failed to send HTC setup complete message. "
375 "Error: %d\n", rc);
376 }
377
378 free(buffer);
379
380 return rc;
381}
382
383/**
384 * Try to fetch ready message from device.
385 * Checks that firmware was successfully loaded on device side.
386 *
387 * @param htc_device HTC device structure.
388 *
389 * @return EOK if succeed, EINVAL if response error, negative error code
390 * otherwise.
391 */
392static int htc_check_ready(htc_device_t *htc_device)
393{
394 size_t buffer_size = htc_device->ath_device->ctrl_response_length;
395 void *buffer = malloc(buffer_size);
396
397 /* Read response from device. */
398 int rc = htc_read_control_message(htc_device, buffer, buffer_size,
399 NULL);
400 if(rc != EOK) {
401 free(buffer);
402 usb_log_error("Failed to receive HTC check ready message. "
403 "Error: %d\n", rc);
404 return rc;
405 }
406
407 uint16_t *message_id = (uint16_t *) ((void *) buffer +
408 sizeof(htc_frame_header_t));
409 if(uint16_t_be2host(*message_id) == HTC_MESSAGE_READY) {
410 rc = EOK;
411 } else {
412 rc = EINVAL;
413 }
414
415 free(buffer);
416
417 return rc;
418}
419
420/**
421 * Initialize HTC device structure.
422 *
423 * @param ath_device Atheros WiFi device connected with this HTC device.
424 * @param htc_device HTC device structure to be initialized.
425 *
426 * @return EOK if succeed, negative error code otherwise.
427 */
428int htc_device_init(ath_t *ath_device, ieee80211_dev_t *ieee80211_dev,
429 htc_device_t *htc_device)
430{
431 fibril_mutex_initialize(&htc_device->rx_lock);
432 fibril_mutex_initialize(&htc_device->tx_lock);
433
434 htc_device->endpoints.ctrl_endpoint = 0;
435
436 htc_device->ath_device = ath_device;
437 htc_device->ieee80211_dev = ieee80211_dev;
438
439 return EOK;
440}
441
442/**
443 * HTC communication initalization.
444 *
445 * @param htc_device HTC device structure.
446 *
447 * @return EOK if succeed, negative error code otherwise.
448 */
449int htc_init(htc_device_t *htc_device)
450{
451 /* First check ready message in device. */
452 int rc = htc_check_ready(htc_device);
453 if(rc != EOK) {
454 usb_log_error("Device is not in ready state after loading "
455 "firmware.\n");
456 return rc;
457 }
458
459 /*
460 * HTC services initialization start.
461 *
462 */
463
464 rc = htc_connect_service(htc_device, WMI_CONTROL_SERVICE,
465 &htc_device->endpoints.wmi_endpoint);
466 if(rc != EOK) {
467 usb_log_error("Error while initalizing WMI service.\n");
468 return rc;
469 }
470
471 rc = htc_connect_service(htc_device, WMI_BEACON_SERVICE,
472 &htc_device->endpoints.beacon_endpoint);
473 if(rc != EOK) {
474 usb_log_error("Error while initalizing beacon service.\n");
475 return rc;
476 }
477
478 rc = htc_connect_service(htc_device, WMI_CAB_SERVICE,
479 &htc_device->endpoints.cab_endpoint);
480 if(rc != EOK) {
481 usb_log_error("Error while initalizing CAB service.\n");
482 return rc;
483 }
484
485 rc = htc_connect_service(htc_device, WMI_UAPSD_SERVICE,
486 &htc_device->endpoints.uapsd_endpoint);
487 if(rc != EOK) {
488 usb_log_error("Error while initalizing UAPSD service.\n");
489 return rc;
490 }
491
492 rc = htc_connect_service(htc_device, WMI_MGMT_SERVICE,
493 &htc_device->endpoints.mgmt_endpoint);
494 if(rc != EOK) {
495 usb_log_error("Error while initalizing MGMT service.\n");
496 return rc;
497 }
498
499 rc = htc_connect_service(htc_device, WMI_DATA_BE_SERVICE,
500 &htc_device->endpoints.data_be_endpoint);
501 if(rc != EOK) {
502 usb_log_error("Error while initalizing data best effort "
503 "service.\n");
504 return rc;
505 }
506
507 rc = htc_connect_service(htc_device, WMI_DATA_BK_SERVICE,
508 &htc_device->endpoints.data_bk_endpoint);
509 if(rc != EOK) {
510 usb_log_error("Error while initalizing data background "
511 "service.\n");
512 return rc;
513 }
514
515 rc = htc_connect_service(htc_device, WMI_DATA_VIDEO_SERVICE,
516 &htc_device->endpoints.data_video_endpoint);
517 if(rc != EOK) {
518 usb_log_error("Error while initalizing data video service.\n");
519 return rc;
520 }
521
522 rc = htc_connect_service(htc_device, WMI_DATA_VOICE_SERVICE,
523 &htc_device->endpoints.data_voice_endpoint);
524 if(rc != EOK) {
525 usb_log_error("Error while initalizing data voice service.\n");
526 return rc;
527 }
528
529 /*
530 * HTC services initialization end.
531 *
532 */
533
534 /* Credits initialization message. */
535 rc = htc_config_credits(htc_device);
536 if(rc != EOK) {
537 usb_log_error("Failed to send HTC config message.\n");
538 return rc;
539 }
540
541 /* HTC setup complete confirmation message. */
542 rc = htc_complete_setup(htc_device);
543 if(rc != EOK) {
544 usb_log_error("Failed to send HTC complete setup message.\n");
545 return rc;
546 }
547
548 usb_log_info("HTC services initialization finished successfully.\n");
549
550 return EOK;
551}
Note: See TracBrowser for help on using the repository browser.