9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/*
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * CDDL HEADER START
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * The contents of this file are subject to the terms of the
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * Common Development and Distribution License (the "License").
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * You may not use this file except in compliance with the License.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * or http://www.opensolaris.org/os/licensing.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * See the License for the specific language governing permissions
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * and limitations under the License.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * When distributing Covered Code, include this CDDL HEADER in each
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * If applicable, add the following below this CDDL HEADER, with the
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * fields enclosed by brackets "[]" replaced with your own identifying
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * information: Portions Copyright [yyyy] [name of copyright owner]
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * CDDL HEADER END
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * Use is subject to license terms.
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#pragma ident "%Z%%M% %I% %E% SMI"
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include <libipmi.h>
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include <stdio.h>
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include <stdlib.h>
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include <string.h>
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include <stdarg.h>
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock#include "ipmi_impl.h"
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj/*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Extracts bits between index h (high, inclusive) and l (low, exclusive) from
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * u, which must be an unsigned integer.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj#define BITX(u, h, l) (((u) >> (l)) & ((1LU << ((h) - (l) + 1LU)) - 1LU))
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/*
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * Error handling
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockint
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_set_error(ipmi_handle_t *ihp, int error, const char *fmt, ...)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock va_list ap;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock va_start(ap, fmt);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock ihp->ih_errno = error;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock if (fmt == NULL)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock ihp->ih_errmsg[0] = '\0';
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock else
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock (void) vsnprintf(ihp->ih_errmsg, sizeof (ihp->ih_errmsg),
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock fmt, ap);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock va_end(ap);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (-1);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockint
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_errno(ipmi_handle_t *ihp)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (ihp->ih_errno);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/* ARGSUSED */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockconst char *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_errmsg(ipmi_handle_t *ihp)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock int i;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock const char *str;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock str = NULL;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (i = 0; ipmi_errno_table[i].int_name != NULL; i++) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (ipmi_errno_table[i].int_value == ihp->ih_errno) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj str = ipmi_errno_table[i].int_name;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock break;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock }
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock }
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock if (str == NULL && (str = strerror(ihp->ih_errno)) == NULL)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock str = "unknown failure";
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock if (ihp->ih_errmsg[0] == '\0')
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (str);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock (void) snprintf(ihp->ih_errbuf, sizeof (ihp->ih_errbuf),
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock "%s: %s", str, ihp->ih_errmsg);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (ihp->ih_errbuf);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/*
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock * Memory allocation
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockvoid *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_alloc(ipmi_handle_t *ihp, size_t size)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock void *ptr;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock if ((ptr = malloc(size)) == NULL)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock (void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (ptr);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockvoid *
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_zalloc(ipmi_handle_t *ihp, size_t size)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock void *ptr;
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock if ((ptr = calloc(size, 1)) == NULL)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock (void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock return (ptr);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrockchar *
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrockipmi_strdup(ipmi_handle_t *ihp, const char *str)
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock{
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock char *ptr;
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock if ((ptr = strdup(str)) == NULL)
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock (void) ipmi_set_error(ihp, EIPMI_NOMEM, NULL);
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock return (ptr);
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock}
1af98250c8b03bdc43d8ac3aac6390221d75b92eeschrock
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock/* ARGSUSED */
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockvoid
9113a79cf228b8f7bd509b1328adf88659dfe218eschrockipmi_free(ipmi_handle_t *ihp, void *ptr)
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock{
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock free(ptr);
9113a79cf228b8f7bd509b1328adf88659dfe218eschrock}
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj/*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Translation between #defines and strings.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjvoid
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjipmi_entity_name(uint8_t id, char *buf, size_t len)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj{
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ipmi_name_trans_t *ntp;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (ntp = &ipmi_entity_table[0]; ntp->int_name != NULL; ntp++) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (ntp->int_value == id) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) strlcpy(buf, ntp->int_name, len);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) snprintf(buf, len, "0x%02x", id);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj}
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjvoid
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjipmi_sensor_type_name(uint8_t type, char *buf, size_t len)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj{
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ipmi_name_trans_t *ntp;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (ntp = &ipmi_sensor_type_table[0]; ntp->int_name != NULL; ntp++) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (ntp->int_value == type) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) strlcpy(buf, ntp->int_name, len);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) snprintf(buf, len, "0x%02x", type);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj}
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robjvoid
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robjipmi_sensor_units_name(uint8_t type, char *buf, size_t len)
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj{
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj ipmi_name_trans_t *ntp;
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj for (ntp = &ipmi_units_type_table[0]; ntp->int_name != NULL; ntp++) {
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj if (ntp->int_value == type) {
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj (void) strlcpy(buf, ntp->int_name, len);
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj return;
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj }
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj }
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj (void) snprintf(buf, len, "0x%02x", type);
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj}
825ba0f20a74fd9c5d0d1ce2c195da2cc88a7f77robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjvoid
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjipmi_sensor_reading_name(uint8_t sensor_type, uint8_t reading_type,
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj char *buf, size_t len)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj{
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj uint8_t val;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ipmi_name_trans_t *ntp;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (reading_type == IPMI_RT_SPECIFIC) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj val = sensor_type;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ntp = &ipmi_sensor_type_table[0];
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj } else {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj val = reading_type;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ntp = &ipmi_reading_type_table[0];
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (; ntp->int_name != NULL; ntp++) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (ntp->int_value == val) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) strlcpy(buf, ntp->int_name, len);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (reading_type == IPMI_RT_SPECIFIC)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) snprintf(buf, len, "%02x/%02x", reading_type,
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj sensor_type);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj else
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) snprintf(buf, len, "%02x", reading_type);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj}
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj/*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Converts a BCD decimal value to an integer.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjint
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjipmi_convert_bcd(int value)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj{
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj int ret = 0;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj int digit;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj int i;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (i = 7; i >= 0; i--) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj digit = ((value & (0xf << (i * 4))) >> (i * 4));
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj ret += digit * 10 * i;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return (ret);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj}
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj/*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * See sections 43.15 and 43.16
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * This is a utility function for decoding the strings that are packed into
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * sensor data records. If the type is 6-bit packed ASCII, then it converts
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * the string to an 8-bit ASCII string and copies that into the suuplied buffer.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * If it is 8-bit ASCII, it copies the string into the supplied buffer as-is.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjvoid
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robjipmi_decode_string(uint8_t type, uint8_t len, char *data, char *buf)
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj{
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj int i, j = 0, chunks, leftovers;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj uint8_t tmp, lo;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (len == 0) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf = '\0';
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj /*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * If the type is 8-bit ASCII, we can simply copy the string and return
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj if (type == 0x3) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj (void) strncpy(buf, data, len);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *(buf+len) = '\0';
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj } else if (type == 0x1 || type == 0x0) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj /*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Yuck - they either used BCD plus encoding, which we don't
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * currently handle, or they used an unspecified encoding type.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * In these cases we'll set buf to an empty string. We still
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * need to return the length so that we can get to the next
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * record.
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf = '\0';
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj return;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj /*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * Otherwise, it's 6-bit packed ASCII, so we have to convert the
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * data first
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj chunks = len / 3;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj leftovers = len % 3;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj /*
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * First we decode the 6-bit string in chunks of 3 bytes as far as
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj * possible
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj */
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj for (i = 0; i < chunks; i++) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 5, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj lo = BITX(*(data+j++), 7, 6);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 3, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = (tmp << 2) | lo;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj lo = BITX(*(data+j++), 7, 4);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 1, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = (tmp << 4) | lo;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j++), 7, 2);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj switch (leftovers) {
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj case 1:
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 5, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj break;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj case 2:
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 5, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj lo = BITX(*(data+j++), 7, 6);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = BITX(*(data+j), 3, 0);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj tmp = (tmp << 2) | lo;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf++ = (char)(tmp + 32);
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj break;
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj }
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj *buf = '\0';
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj}