HelenOS sources
This source file includes following definitions.
- wmi_reg_read
- wmi_reg_write
- wmi_reg_set_clear_bit
- wmi_reg_set_bit
- wmi_reg_clear_bit
- wmi_reg_buffer_write
- wmi_send_command
#include <usb/debug.h>
#include <errno.h>
#include <str_error.h>
#include <stdlib.h>
#include <mem.h>
#include <byteorder.h>
#include "wmi.h"
errno_t wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, uint32_t *res)
{
uint32_t cmd_value = host2uint32_t_be(reg_offset);
void *resp_buffer =
malloc(htc_device->ath_device->ctrl_response_length);
errno_t rc = wmi_send_command(htc_device, WMI_REG_READ,
(uint8_t *) &cmd_value, sizeof(cmd_value), resp_buffer);
if (rc != EOK) {
usb_log_error("Failed to read registry value.\n");
return rc;
}
uint32_t *resp_value = (uint32_t *) ((void *) resp_buffer +
sizeof(htc_frame_header_t) + sizeof(wmi_command_header_t));
*res = uint32_t_be2host(*resp_value);
return rc;
}
errno_t wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, uint32_t val)
{
uint32_t cmd_buffer[] = {
host2uint32_t_be(reg_offset),
host2uint32_t_be(val)
};
void *resp_buffer =
malloc(htc_device->ath_device->ctrl_response_length);
errno_t rc = wmi_send_command(htc_device, WMI_REG_WRITE,
(uint8_t *) &cmd_buffer, sizeof(cmd_buffer), resp_buffer);
free(resp_buffer);
if (rc != EOK) {
usb_log_error("Failed to write registry value.\n");
return rc;
}
return rc;
}
errno_t wmi_reg_set_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
uint32_t set_bit, uint32_t clear_bit)
{
uint32_t value;
errno_t rc = wmi_reg_read(htc_device, reg_offset, &value);
if (rc != EOK) {
usb_log_error("Failed to read registry value in RMW "
"function.\n");
return rc;
}
value &= ~clear_bit;
value |= set_bit;
rc = wmi_reg_write(htc_device, reg_offset, value);
if (rc != EOK) {
usb_log_error("Failed to write registry value in RMW "
"function.\n");
return rc;
}
return rc;
}
errno_t wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset,
uint32_t set_bit)
{
return wmi_reg_set_clear_bit(htc_device, reg_offset, set_bit, 0);
}
errno_t wmi_reg_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
uint32_t clear_bit)
{
return wmi_reg_set_clear_bit(htc_device, reg_offset, 0, clear_bit);
}
errno_t wmi_reg_buffer_write(htc_device_t *htc_device, wmi_reg_t *reg_buffer,
size_t elements)
{
size_t buffer_size = sizeof(wmi_reg_t) * elements;
void *buffer = malloc(buffer_size);
void *resp_buffer =
malloc(htc_device->ath_device->ctrl_response_length);
for (size_t i = 0; i < elements; i++) {
wmi_reg_t *buffer_element = ®_buffer[i];
wmi_reg_t *buffer_it = (wmi_reg_t *)
((void *) buffer + i * sizeof(wmi_reg_t));
buffer_it->offset =
host2uint32_t_be(buffer_element->offset);
buffer_it->value =
host2uint32_t_be(buffer_element->value);
}
errno_t rc = wmi_send_command(htc_device, WMI_REG_WRITE,
(uint8_t *) buffer, buffer_size, resp_buffer);
free(buffer);
free(resp_buffer);
if (rc != EOK) {
usb_log_error("Failed to write multi registry value.\n");
return rc;
}
return rc;
}
errno_t wmi_send_command(htc_device_t *htc_device, wmi_command_t command_id,
uint8_t *command_buffer, uint32_t command_length, void *response_buffer)
{
size_t header_size = sizeof(wmi_command_header_t) +
sizeof(htc_frame_header_t);
size_t buffer_size = header_size + command_length;
void *buffer = malloc(buffer_size);
if (buffer == NULL) {
usb_log_error("Failed to allocate WMI message buffer (out of memory).\n");
return ENOMEM;
}
if (command_buffer != NULL)
memcpy(buffer + header_size, command_buffer, command_length);
wmi_command_header_t *wmi_header = (wmi_command_header_t *)
((void *) buffer + sizeof(htc_frame_header_t));
wmi_header->command_id = host2uint16_t_be(command_id);
wmi_header->sequence_number =
host2uint16_t_be(++htc_device->sequence_number);
errno_t rc = htc_send_control_message(htc_device, buffer, buffer_size,
htc_device->endpoints.wmi_endpoint);
free(buffer);
if (rc != EOK) {
usb_log_error("Failed to send WMI message. Error: %s\n", str_error_name(rc));
return rc;
}
bool clean_resp_buffer = false;
size_t response_buffer_size =
htc_device->ath_device->ctrl_response_length;
if (response_buffer == NULL) {
response_buffer = malloc(response_buffer_size);
clean_resp_buffer = true;
}
uint16_t cmd_id;
do {
rc = htc_read_control_message(htc_device, response_buffer,
response_buffer_size, NULL);
if (rc != EOK) {
usb_log_error("Failed to receive WMI message response. "
"Error: %s\n", str_error_name(rc));
return rc;
}
if (response_buffer_size < sizeof(htc_frame_header_t) +
sizeof(wmi_command_header_t)) {
usb_log_error("Corrupted response received.\n");
return EINVAL;
}
wmi_command_header_t *wmi_hdr = (wmi_command_header_t *)
((void *) response_buffer + sizeof(htc_frame_header_t));
cmd_id = uint16_t_be2host(wmi_hdr->command_id);
} while (cmd_id & WMI_MGMT_CMD_MASK);
if (clean_resp_buffer)
free(response_buffer);
return rc;
}
HelenOS homepage, sources at GitHub