diff options
author | root <root@lamia.panaceas.james.local> | 2017-01-16 12:16:27 +0000 |
---|---|---|
committer | root <root@lamia.panaceas.james.local> | 2017-01-16 12:16:27 +0000 |
commit | 4477c392b87bdaaae6780ccadc9a4f4923f2b344 (patch) | |
tree | daef2ccf9b2b1cc8c79e7bd46b379a24f06ce515 /src/twa.c | |
parent | 8ee35c49abfcc5118b085fe63994b533944b4595 (diff) | |
download | twa_t-4477c392b87bdaaae6780ccadc9a4f4923f2b344.tar.gz twa_t-4477c392b87bdaaae6780ccadc9a4f4923f2b344.tar.bz2 twa_t-4477c392b87bdaaae6780ccadc9a4f4923f2b344.zip |
add source
Diffstat (limited to 'src/twa.c')
-rw-r--r-- | src/twa.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/twa.c b/src/twa.c new file mode 100644 index 0000000..9cd89b2 --- /dev/null +++ b/src/twa.c @@ -0,0 +1,157 @@ +/* + * twa.c: + * + * Copyright (c) 2017 James McKenzie <foss@madingley.org>, + * All rights reserved. + * + */ + +#include "project.h" + +ssize_t +twa_get_parameter (int fd, int table_id, int parameter_id, void *data, + size_t data_len) +{ + + TW_Command *command; + TW_Param_Apache *param; + TW_Command_Apache_Header *header; + TW_Ioctl_Buf_Apache *tw_ioctl_apache; + int rc; + size_t buffer_len, ret_len; + char error[512]; + + buffer_len = data_len + sizeof (TW_Param_Apache); + + tw_ioctl_apache = xmalloc (sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + memset (tw_ioctl_apache, 0, sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + tw_ioctl_apache->driver_command.control_code = + TW_IOCTL_FIRMWARE_PASS_THROUGH; + tw_ioctl_apache->driver_command.buffer_length = buffer_len; + + header = + (TW_Command_Apache_Header *) & (tw_ioctl_apache->firmware_command.header); + header->header_desc.size_header = sizeof (*header); + + command = + (TW_Command *) & (tw_ioctl_apache->firmware_command.command.oldcommand); + + command->byte0.opcode = TW_OP_GET_PARAM; + command->byte0.sgl_offset = 0x2; + + command->size = TW_COMMAND_SIZE; + + command->byte6.parameter_count = cpu_to_le16 (1); + + param = (TW_Param_Apache *) tw_ioctl_apache->data_buffer; + + param->table_id = cpu_to_le16 (table_id | 0x8000); + param->parameter_id = cpu_to_le16 (parameter_id); + param->parameter_size_bytes = cpu_to_le16 (data_len); + + rc = ioctl (fd, TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache); + + if (rc) + { + fprintf (stderr, + "twa_get_parameter: ioctl TW_IOCTL_FIRMWARE_PASS_THROUGH failed: %m\n"); + return -1; + } + + if (header->status_block.error) + { + memset (error, 0, sizeof (error)); + memcpy (error, header->err_specific_desc, + sizeof (header->err_specific_desc)); + + fprintf (stderr, + "twa_get_parameter: controller returns error: (0x%x) %s\n", + le16_to_cpu (header->status_block.error), error + 1); + return -1; + } + + ret_len = le16_to_cpu (param->actual_parameter_size_bytes); + + if (ret_len > data_len) + { + fprintf (stderr, + "twa_get_parameter: buffer passed for table 0x%x, parameter 0x%x too short: given %d bytes need %d\n", + table_id, parameter_id, data_len, ret_len); + return -1; + } + + memcpy (data, param->data, ret_len); + + return ret_len; +} + +int +twa_set_parameter (int fd, int table_id, int parameter_id, void *data, + size_t data_len) +{ + + TW_Command *command; + TW_Param_Apache *param; + TW_Command_Apache_Header *header; + TW_Ioctl_Buf_Apache *tw_ioctl_apache; + int rc; + size_t buffer_len, ret_len; + char error[512]; + + buffer_len = data_len + sizeof (TW_Param_Apache); + + tw_ioctl_apache = xmalloc (sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + memset (tw_ioctl_apache, 0, sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + tw_ioctl_apache->driver_command.control_code = + TW_IOCTL_FIRMWARE_PASS_THROUGH; + tw_ioctl_apache->driver_command.buffer_length = buffer_len; + + header = + (TW_Command_Apache_Header *) & (tw_ioctl_apache->firmware_command.header); + header->header_desc.size_header = sizeof (*header); + + command = + (TW_Command *) & (tw_ioctl_apache->firmware_command.command.oldcommand); + + command->byte0.opcode = TW_OP_SET_PARAM; + command->byte0.sgl_offset = 0x2; + + command->size = TW_COMMAND_SIZE; + + command->byte6.parameter_count = cpu_to_le16 (1); + + param = (TW_Param_Apache *) tw_ioctl_apache->data_buffer; + + param->table_id = cpu_to_le16 (table_id | 0x8000); + param->parameter_id = cpu_to_le16 (parameter_id); + param->parameter_size_bytes = cpu_to_le16 (data_len); + + memcpy (param->data, data, data_len); + + rc = ioctl (fd, TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache); + + if (rc) + { + fprintf (stderr, + "twa_get_parameter: ioctl TW_IOCTL_FIRMWARE_PASS_THROUGH failed: %m\n"); + return -1; + } + + if (header->status_block.error) + { + memset (error, 0, sizeof (error)); + memcpy (error, header->err_specific_desc, + sizeof (header->err_specific_desc)); + + fprintf (stderr, + "twa_get_parameter: controller returns error: (0x%x) %s\n", + le16_to_cpu (header->status_block.error), error + 1); + return -1; + } + + return 0; +} |