source: mainline/uspace/drv/nic/ar9271/wmi.c@ 1dcc0b9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1dcc0b9 was 1dcc0b9, checked in by Jan Kolarik <kolarik@…>, 11 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: 8.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 wmi.c
30 *
31 * Implementation of Atheros WMI communication.
32 *
33 */
34
35#include <usb/debug.h>
36
37#include <malloc.h>
38#include <mem.h>
39#include <byteorder.h>
40
41#include "wmi.h"
42
43/**
44 * WMI registry read.
45 *
46 * @param htc_device HTC device structure.
47 * @param reg_offset Registry offset (address) to be read.
48 * @param res Stored result.
49 *
50 * @return EOK if succeed, negative error code otherwise.
51 */
52int wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, uint32_t *res)
53{
54 uint32_t cmd_value = host2uint32_t_be(reg_offset);
55
56 void *resp_buffer =
57 malloc(htc_device->ath_device->ctrl_response_length);
58
59 int rc = wmi_send_command(htc_device, WMI_REG_READ,
60 (uint8_t *) &cmd_value, sizeof(cmd_value), resp_buffer);
61
62 if(rc != EOK) {
63 usb_log_error("Failed to read registry value.\n");
64 return rc;
65 }
66
67 uint32_t *resp_value = (uint32_t *) ((void*) resp_buffer +
68 sizeof(htc_frame_header_t) +
69 sizeof(wmi_command_header_t));
70
71 *res = uint32_t_be2host(*resp_value);
72
73 return rc;
74}
75
76/**
77 * WMI registry write.
78 *
79 * @param htc_device HTC device structure.
80 * @param reg_offset Registry offset (address) to be written.
81 * @param val Value to be written
82 *
83 * @return EOK if succeed, negative error code otherwise.
84 */
85int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, uint32_t val)
86{
87 uint32_t cmd_buffer[] = {
88 host2uint32_t_be(reg_offset),
89 host2uint32_t_be(val)
90 };
91
92 void *resp_buffer =
93 malloc(htc_device->ath_device->ctrl_response_length);
94
95 int rc = wmi_send_command(htc_device, WMI_REG_WRITE,
96 (uint8_t *) &cmd_buffer, sizeof(cmd_buffer), resp_buffer);
97
98 free(resp_buffer);
99
100 if(rc != EOK) {
101 usb_log_error("Failed to write registry value.\n");
102 return rc;
103 }
104
105 return rc;
106}
107
108/**
109 * WMI registry set or clear specified bits.
110 *
111 * @param htc_device HTC device structure.
112 * @param reg_offset Registry offset (address) to be written.
113 * @param set_bit Bit to be set.
114 * @param clear_bit Bit to be cleared.
115 *
116 * @return EOK if succeed, negative error code otherwise.
117 */
118int wmi_reg_set_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
119 uint32_t set_bit, uint32_t clear_bit)
120{
121 uint32_t value;
122
123 int rc = wmi_reg_read(htc_device, reg_offset, &value);
124 if(rc != EOK) {
125 usb_log_error("Failed to read registry value in RMW "
126 "function.\n");
127 return rc;
128 }
129
130 value &= ~clear_bit;
131 value |= set_bit;
132
133 rc = wmi_reg_write(htc_device, reg_offset, value);
134 if(rc != EOK) {
135 usb_log_error("Failed to write registry value in RMW "
136 "function.\n");
137 return rc;
138 }
139
140 return rc;
141}
142
143/**
144 * WMI registry set specified bit.
145 *
146 * @param htc_device HTC device structure.
147 * @param reg_offset Registry offset (address) to be written.
148 * @param set_bit Bit to be set.
149 *
150 * @return EOK if succeed, negative error code otherwise.
151 */
152int wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset,
153 uint32_t set_bit)
154{
155 return wmi_reg_set_clear_bit(htc_device, reg_offset, set_bit, 0);
156}
157
158/**
159 * WMI registry clear specified bit.
160 *
161 * @param htc_device HTC device structure.
162 * @param reg_offset Registry offset (address) to be written.
163 * @param clear_bit Bit to be cleared.
164 *
165 * @return EOK if succeed, negative error code otherwise.
166 */
167int wmi_reg_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
168 uint32_t clear_bit)
169{
170 return wmi_reg_set_clear_bit(htc_device, reg_offset, 0, clear_bit);
171}
172
173/**
174 * WMI multi registry write.
175 *
176 * @param htc_device HTC device structure.
177 * @param reg_buffer Array of registry values to be written.
178 * @param elements Number of elements in array.
179 *
180 * @return EOK if succeed, negative error code otherwise.
181 */
182int wmi_reg_buffer_write(htc_device_t *htc_device, wmi_reg_t *reg_buffer,
183 size_t elements)
184{
185 size_t buffer_size = sizeof(wmi_reg_t) * elements;
186 void *buffer = malloc(buffer_size);
187 void *resp_buffer =
188 malloc(htc_device->ath_device->ctrl_response_length);
189
190 /* Convert values to correct endianness. */
191 for(size_t i = 0; i < elements; i++) {
192 wmi_reg_t *buffer_element = &reg_buffer[i];
193 wmi_reg_t *buffer_it = (wmi_reg_t *)
194 ((void *) buffer + i*sizeof(wmi_reg_t));
195 buffer_it->offset =
196 host2uint32_t_be(buffer_element->offset);
197 buffer_it->value =
198 host2uint32_t_be(buffer_element->value);
199 }
200
201 int rc = wmi_send_command(htc_device, WMI_REG_WRITE,
202 (uint8_t *) buffer, buffer_size, resp_buffer);
203
204 free(buffer);
205 free(resp_buffer);
206
207 if(rc != EOK) {
208 usb_log_error("Failed to write multi registry value.\n");
209 return rc;
210 }
211
212 return rc;
213}
214
215/**
216 * Send WMI message to HTC device.
217 *
218 * @param htc_device HTC device structure.
219 * @param command_id Command identification.
220 * @param command_buffer Buffer with command data.
221 * @param command_length Length of command data.
222 * @param response_buffer Buffer with response data.
223 *
224 * @return EOK if succeed, negative error code otherwise.
225 */
226int wmi_send_command(htc_device_t *htc_device, wmi_command_t command_id,
227 uint8_t *command_buffer, uint32_t command_length, void *response_buffer)
228{
229 size_t header_size = sizeof(wmi_command_header_t) +
230 sizeof(htc_frame_header_t);
231 size_t buffer_size = header_size + command_length;
232 void *buffer = malloc(buffer_size);
233
234 if(command_buffer != NULL) {
235 memcpy(buffer+header_size, command_buffer, command_length);
236 }
237
238 /* Set up WMI header */
239 wmi_command_header_t *wmi_header = (wmi_command_header_t *)
240 ((void *) buffer + sizeof(htc_frame_header_t));
241 wmi_header->command_id =
242 host2uint16_t_be(command_id);
243 wmi_header->sequence_number =
244 host2uint16_t_be(++htc_device->sequence_number);
245
246 /* Send message. */
247 int rc = htc_send_control_message(htc_device, buffer, buffer_size,
248 htc_device->endpoints.wmi_endpoint);
249 if(rc != EOK) {
250 free(buffer);
251 usb_log_error("Failed to send WMI message. Error: %d\n", rc);
252 return rc;
253 }
254
255 free(buffer);
256
257 bool clean_resp_buffer = false;
258 size_t response_buffer_size =
259 htc_device->ath_device->ctrl_response_length;
260 if(response_buffer == NULL) {
261 response_buffer = malloc(response_buffer_size);
262 clean_resp_buffer = true;
263 }
264
265 /* Read response. */
266 /* TODO: Ignoring WMI management RX messages ~ TX statuses etc. */
267 uint16_t cmd_id;
268 do {
269 rc = htc_read_control_message(htc_device, response_buffer,
270 response_buffer_size, NULL);
271 if(rc != EOK) {
272 free(buffer);
273 usb_log_error("Failed to receive WMI message response. "
274 "Error: %d\n", rc);
275 return rc;
276 }
277
278 if(response_buffer_size < sizeof(htc_frame_header_t) +
279 sizeof(wmi_command_header_t)) {
280 free(buffer);
281 usb_log_error("Corrupted response received.\n");
282 return EINVAL;
283 }
284
285 wmi_command_header_t *wmi_hdr = (wmi_command_header_t *)
286 ((void*) response_buffer + sizeof(htc_frame_header_t));
287 cmd_id = uint16_t_be2host(wmi_hdr->command_id);
288 } while(cmd_id & WMI_MGMT_CMD_MASK);
289
290 if(clean_resp_buffer) {
291 free(response_buffer);
292 }
293
294 return rc;
295}
Note: See TracBrowser for help on using the repository browser.