ID:390 - Support for new Communication Interface (USB Medium)

This feature request is for adding support for USB Medium as an interface in
IPMITool. AMI BMC (OEM feature) provides Virtual USB devices in the host as
part of its feature list. IPMITool can use this 'Virtual USB device' as a
medium for Inband communication with BMC.

Just like any other interface, use can just give 'ipmitool -I usb xxxx' to
communicate with the BMC via USB Interface.
This commit is contained in:
Zdenek Styblik 2015-09-11 19:01:31 +02:00
parent 13a2a29156
commit e2c5b322d8
5 changed files with 684 additions and 2 deletions

View File

@ -59,6 +59,7 @@ dnl
xenable_intf_bmc=no xenable_intf_bmc=no
xenable_intf_imb=yes xenable_intf_imb=yes
xenable_intf_open=yes xenable_intf_open=yes
xenable_intf_usb=yes
xenable_intf_lipmi=yes xenable_intf_lipmi=yes
#xenable_intf_serial=yes #xenable_intf_serial=yes
xenable_intf_dummy=no xenable_intf_dummy=no
@ -197,6 +198,22 @@ if test "x$xenable_intf_lan" = "xyes"; then
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la" IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB lan/libintf_lan.la"
fi fi
dnl enable IPMI USB interface
AC_ARG_ENABLE([intf-usb],
[AC_HELP_STRING([--enable-intf-usb],
[enable IPMI USB interface [default=yes]])],
[xenable_intf_usb=$enableval],
[xenable_intf_usb=yes])
if test "x$xenable_intf_usb" = "xstatic" || test "x$xenable_intf_usb" = "xplugin"; then
xenable_intf_usb=yes
fi
if test "x$xenable_intf_usb" = "xyes"; then
AC_DEFINE(IPMI_INTF_USB, [1], [Define to 1 to enable USB interface.])
AC_SUBST(INTF_USB, [usb])
AC_SUBST(INTF_USB_LIB, [libintf_usb.la])
IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la"
fi
dnl enable IPMIv2.0 RMCP+ LAN interface dnl enable IPMIv2.0 RMCP+ LAN interface
AC_ARG_ENABLE([intf-lanplus], AC_ARG_ENABLE([intf-lanplus],
[AC_HELP_STRING([--enable-intf-lanplus], [AC_HELP_STRING([--enable-intf-lanplus],
@ -638,6 +655,7 @@ AC_CONFIG_FILES([Makefile
src/plugins/free/Makefile src/plugins/free/Makefile
src/plugins/imb/Makefile src/plugins/imb/Makefile
src/plugins/bmc/Makefile src/plugins/bmc/Makefile
src/plugins/usb/Makefile
src/plugins/lipmi/Makefile src/plugins/lipmi/Makefile
src/plugins/serial/Makefile src/plugins/serial/Makefile
src/plugins/dummy/Makefile]) src/plugins/dummy/Makefile])
@ -654,6 +672,7 @@ AC_MSG_RESULT([ open : $xenable_intf_open])
AC_MSG_RESULT([ free : $xenable_intf_free]) AC_MSG_RESULT([ free : $xenable_intf_free])
AC_MSG_RESULT([ imb : $xenable_intf_imb]) AC_MSG_RESULT([ imb : $xenable_intf_imb])
AC_MSG_RESULT([ bmc : $xenable_intf_bmc]) AC_MSG_RESULT([ bmc : $xenable_intf_bmc])
AC_MSG_RESULT([ usb : $xenable_intf_usb])
AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi]) AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi])
AC_MSG_RESULT([ serial : $xenable_intf_serial]) AC_MSG_RESULT([ serial : $xenable_intf_serial])
AC_MSG_RESULT([ dummy : $xenable_intf_dummy]) AC_MSG_RESULT([ dummy : $xenable_intf_dummy])

View File

@ -32,8 +32,8 @@ MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb
noinst_LTLIBRARIES = libintf.la noinst_LTLIBRARIES = libintf.la
libintf_la_SOURCES = ipmi_intf.c libintf_la_SOURCES = ipmi_intf.c

View File

@ -85,6 +85,9 @@ extern struct ipmi_intf ipmi_serial_bm_intf;
#ifdef IPMI_INTF_DUMMY #ifdef IPMI_INTF_DUMMY
extern struct ipmi_intf ipmi_dummy_intf; extern struct ipmi_intf ipmi_dummy_intf;
#endif #endif
#ifdef IPMI_INTF_USB
extern struct ipmi_intf ipmi_usb_intf;
#endif
struct ipmi_intf * ipmi_intf_table[] = { struct ipmi_intf * ipmi_intf_table[] = {
#ifdef IPMI_INTF_OPEN #ifdef IPMI_INTF_OPEN
@ -114,6 +117,9 @@ struct ipmi_intf * ipmi_intf_table[] = {
#endif #endif
#ifdef IPMI_INTF_DUMMY #ifdef IPMI_INTF_DUMMY
&ipmi_dummy_intf, &ipmi_dummy_intf,
#endif
#ifdef IPMI_INTF_USB
&ipmi_usb_intf,
#endif #endif
NULL NULL
}; };

View File

@ -0,0 +1,40 @@
#
# Copyright (c) 2015 American Megatrends, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification,are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_srcdir)/include
EXTRA_LTLIBRARIES = libintf_usb.la
noinst_LTLIBRARIES = @INTF_USB_LIB@
libintf_usb_la_LIBADD = $(top_builddir)/lib/libipmitool.la
libintf_usb_la_SOURCES = usb.c

617
src/plugins/usb/usb.c Normal file
View File

@ -0,0 +1,617 @@
/*
* Copyright (c) 2015 American Megatrends, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define _BSD_SOURCE
#include <ipmitool/helper.h>
#include <ipmitool/log.h>
#include <ipmitool/bswap.h>
#include <ipmitool/ipmi.h>
#include <ipmitool/ipmi_intf.h>
#include <ipmitool/ipmi_oem.h>
#include <ipmitool/ipmi_strings.h>
#include <ipmitool/ipmi_constants.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define PACKED __attribute__ ((packed))
#define BEGIN_SIG "$G2-CONFIG-HOST$"
#define BEGIN_SIG_LEN 16
#define MAX_REQUEST_SIZE 64 * 1024
#define CMD_RESERVED 0x0000
#define SCSI_AMICMD_CURI_WRITE 0xE2
#define SCSI_AMICMD_CURI_READ 0xE3
#define SCSI_AMIDEF_CMD_SECTOR 0x01
#define SCSI_AMIDEF_DATA_SECTOR 0x02
#define ERR_SUCCESS 0 /* Success */
#define ERR_BIG_DATA 1 /* Too Much Data */
#define ERR_NO_DATA 2 /* No/Less Data Available */
#define ERR_UNSUPPORTED 3 /* Unsupported Command */
#define IN_PROCESS 0x8000 /* Bit 15 of Status */
#define SCSI_AMICMD_ID 0xEE
/* SCSI Command Packets */
typedef struct {
unsigned char OpCode;
unsigned char Lun;
unsigned int Lba;
union {
struct {
unsigned char Reserved6;
unsigned short Length;
unsigned char Reserved9[3];
} PACKED Cmd10;
struct Len32 {
unsigned int Length32;
unsigned char Reserved10[2];
} PACKED Cmd12;
} PACKED CmdLen;
} PACKED SCSI_COMMAND_PACKET;
typedef struct {
uint8_t byNetFnLUN;
uint8_t byCmd;
uint8_t byData[MAX_REQUEST_SIZE];
} PACKED IPMIUSBRequest_T;
typedef struct {
uint8_t BeginSig[BEGIN_SIG_LEN];
uint16_t Command;
uint16_t Status;
uint32_t DataInLen;
uint32_t DataOutLen;
uint32_t InternalUseDataIn;
uint32_t InternalUseDataOut;
} CONFIG_CMD;
static int ipmi_usb_setup(struct ipmi_intf *intf);
static struct ipmi_rs *ipmi_usb_send_cmd(struct ipmi_intf *intf,
struct ipmi_rq *req);
struct ipmi_intf ipmi_usb_intf = {
.name = "usb",
.desc = "IPMI USB Interface(OEM Interface for AMI Devices)",
.setup = ipmi_usb_setup,
.sendrecv = ipmi_usb_send_cmd,
};
int
scsiProbeNew(int *num_ami_devices, int *sg_nos)
{
int inplen = *num_ami_devices;
int numdevfound = 0;
char linebuf[81];
char vendor[81];
int lineno = 0;
FILE *fp;
fp = fopen("/proc/scsi/sg/device_strs", "r");
if (fp == NULL) {
/* Return 1 on error */
return 1;
}
while (1) {
/* Read line by line and search for "AMI" */
if (fgets(linebuf, 80, fp) == NULL) {
if (fp != NULL) {
fclose(fp);
}
/* Return 1 on error */
return 1;
}
if (sscanf(linebuf, "%s", vendor) == 1) {
if (strncmp(vendor, "AMI", strlen("AMI")) == 0) {
numdevfound++;
sg_nos[numdevfound - 1] = lineno;
if (numdevfound == inplen) {
break;
}
}
lineno++;
}
}
*num_ami_devices = numdevfound;
if (fp != NULL) {
fclose(fp);
}
return 0;
}
int
OpenCD(struct ipmi_intf *intf, char *CDName)
{
intf->fd = open(CDName, O_RDWR);
if (intf->fd == (-1)) {
lprintf(LOG_ERR, "OpenCD:Unable to open device, %s",
strerror(errno));
return 1;
}
return 0;
}
int
sendscsicmd_SGIO(int cd_desc, unsigned char *cdb_buf, unsigned char cdb_len,
void *data_buf, unsigned int *data_len, int direction,
void *sense_buf, unsigned char slen, unsigned int timeout)
{
sg_io_hdr_t io_hdr;
/* Prepare command */
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cdb_len;
/* Transfer direction and length */
io_hdr.dxfer_direction = direction;
io_hdr.dxfer_len = *data_len;
io_hdr.dxferp = data_buf;
io_hdr.cmdp = cdb_buf;
io_hdr.sbp = (unsigned char *)sense_buf;
io_hdr.mx_sb_len = slen;
io_hdr.timeout = timeout;
if (!timeout) {
io_hdr.timeout = 20000;
}
if (ioctl(cd_desc, SG_IO, &io_hdr) < 0) {
lprintf(LOG_ERR, "sendscsicmd_SGIO: SG_IO ioctl error");
return 1;
} else {
if (io_hdr.status != 0) {
return 1;
}
}
if (!timeout) {
return 0;
}
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - Not OK");
} else {
lprintf(LOG_DEBUG, "sendscsicmd_SGIO: SG_INFO_OK - OK");
return 0;
}
return 1;
}
int
AMI_SPT_CMD_Identify(int cd_desc, char *szSignature)
{
SCSI_COMMAND_PACKET IdPkt = {0};
int ret;
unsigned int siglen = 10;
IdPkt.OpCode = SCSI_AMICMD_ID;
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&IdPkt,
10, szSignature, &siglen, SG_DXFER_FROM_DEV,
NULL, 0, 5000);
return ret;
}
int
IsG2Drive(int cd_desc)
{
char szSignature[15];
int ret;
memset(szSignature, 0, 15);
flock(cd_desc, LOCK_EX);
ret = AMI_SPT_CMD_Identify(cd_desc, szSignature);
flock(cd_desc, LOCK_UN);
if (ret != 0) {
lprintf(LOG_DEBUG,
"IsG2Drive:Unable to send ID command to the device");
return 1;
}
if (strncmp(szSignature, "$$$AMI$$$", strlen("$$$AMI$$$")) != 0) {
lprintf(LOG_ERR,
"IsG2Drive:Signature mismatch when ID command sent");
return 1;
}
return 0;
}
int
FindG2CDROM(struct ipmi_intf *intf)
{
int err = 0;
char device[256];
int devarray[8];
int numdev = 8;
int iter;
err = scsiProbeNew(&numdev, devarray);
if (err == 0 && numdev > 0) {
for (iter = 0; iter < numdev; iter++) {
sprintf(device, "/dev/sg%d", devarray[iter]);
if (!OpenCD(intf, device)) {
if (!IsG2Drive(intf->fd)) {
lprintf(LOG_DEBUG, "USB Device found");
return 1;
}
close(intf->fd);
}
}
} else {
lprintf(LOG_DEBUG, "Unable to find Virtual CDROM Device");
}
return 0;
}
static int
ipmi_usb_setup(struct ipmi_intf *intf)
{
if (FindG2CDROM(intf) == 0) {
lprintf(LOG_ERR, "Error in USB session setup \n");
return (-1);
}
intf->opened = 1;
return 0;
}
void
InitCmdHeader(CONFIG_CMD *pG2CDCmdHeader)
{
memset(pG2CDCmdHeader, 0, sizeof(CONFIG_CMD));
memcpy((char *)pG2CDCmdHeader->BeginSig, BEGIN_SIG, BEGIN_SIG_LEN);
}
int
AMI_SPT_CMD_SendCmd(int cd_desc, char *Buffer, char type, uint16_t buflen,
unsigned int timeout)
{
SCSI_COMMAND_PACKET Cmdpkt;
char sensebuff[32];
int ret;
unsigned int pktLen;
int count = 3;
memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
Cmdpkt.OpCode = SCSI_AMICMD_CURI_WRITE;
Cmdpkt.Lba = htonl(type);
Cmdpkt.CmdLen.Cmd10.Length = htons(1);
pktLen = buflen;
while (count > 0) {
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
10, Buffer, &pktLen, SG_DXFER_TO_DEV,
sensebuff, 32, timeout);
count--;
if (ret == 0) {
break;
} else {
ret = (-1);
}
}
return ret;
}
int
AMI_SPT_CMD_RecvCmd(int cd_desc, char *Buffer, char type, uint16_t buflen)
{
SCSI_COMMAND_PACKET Cmdpkt;
char sensebuff[32];
int ret;
unsigned int pktLen;
int count = 3;
memset(&Cmdpkt, 0, sizeof(SCSI_COMMAND_PACKET));
Cmdpkt.OpCode = SCSI_AMICMD_CURI_READ;
Cmdpkt.Lba = htonl(type);
Cmdpkt.CmdLen.Cmd10.Length = htons(1);
pktLen = buflen;
while (count > 0) {
ret = sendscsicmd_SGIO(cd_desc, (unsigned char *)&Cmdpkt,
10, Buffer, &pktLen, SG_DXFER_FROM_DEV,
sensebuff, 32, 5000);
count--;
if (0 == ret) {
break;
} else {
ret = (-1);
}
}
return ret;
}
int
ReadCD(int cd_desc, char CmdData, char *Buffer, uint32_t DataLen)
{
int ret;
ret = AMI_SPT_CMD_RecvCmd(cd_desc, Buffer, CmdData, DataLen);
if (ret != 0) {
lprintf(LOG_ERR, "Error while reading CD-Drive");
return (-1);
}
return 0;
}
int
WriteCD(int cd_desc, char CmdData, char *Buffer, unsigned int timeout,
uint32_t DataLen)
{
int ret;
ret = AMI_SPT_CMD_SendCmd(cd_desc, Buffer, CmdData, DataLen, timeout);
if (ret != 0) {
lprintf(LOG_ERR, "Error while writing to CD-Drive");
return (-1);
}
return 0;
}
int
WriteSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
uint32_t NumBytes, uint32_t timeout)
{
uint32_t BytesWritten = 0;
int retVal;
if (NumBytes == 0) {
return 0;
}
while (BytesWritten < NumBytes) {
if ((retVal = WriteCD(intf->fd, Sector,
(Buffer + BytesWritten),
timeout, NumBytes)) != 0) {
return retVal;
}
BytesWritten += NumBytes;
}
return 0;
}
int
ReadSplitData(struct ipmi_intf *intf, char *Buffer, char Sector,
uint32_t NumBytes)
{
uint32_t BytesRead = 0;
if (NumBytes == 0) {
return 0;
}
while (BytesRead < NumBytes) {
if (ReadCD(intf->fd, Sector, (Buffer + BytesRead),
NumBytes) == (-1)) {
return 1;
}
BytesRead += NumBytes;
}
return 0;
}
int
WaitForCommandCompletion(struct ipmi_intf *intf, CONFIG_CMD *pG2CDCmdHeader,
uint32_t timeout, uint32_t DataLen)
{
uint32_t TimeCounter = 0;
do {
if (ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
(char *)(pG2CDCmdHeader), DataLen) == (-1)) {
lprintf(LOG_ERR, "ReadCD returned ERROR");
return 1;
}
if (pG2CDCmdHeader->Status & IN_PROCESS) {
usleep(1000);
if (timeout > 0) {
TimeCounter++;
if (TimeCounter == (timeout + 1)) {
return 2;
}
}
} else {
lprintf(LOG_DEBUG, "Command completed");
break;
}
} while (1);
return 0;
}
int
SendDataToUSBDriver(struct ipmi_intf *intf, char *ReqBuffer,
unsigned int ReqBuffLen, unsigned char *ResBuffer,
int *ResBuffLen, unsigned int timeout)
{
char CmdHeaderBuffer[sizeof(CONFIG_CMD)];
int retVal;
int waitretval = 0;
unsigned int to = 0;
uint32_t DataLen = 0;
CONFIG_CMD *pG2CDCmdHeader = (CONFIG_CMD *)CmdHeaderBuffer;
/* FillHeader */
InitCmdHeader(pG2CDCmdHeader);
/* Set command number */
pG2CDCmdHeader->Command = CMD_RESERVED;
/* Fill Lengths */
pG2CDCmdHeader->DataOutLen = *ResBuffLen;
pG2CDCmdHeader->DataInLen = ReqBuffLen;
if (!timeout) {
to = 3000;
}
DataLen = sizeof(CONFIG_CMD);
if (WriteCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
(char *)(pG2CDCmdHeader), to, DataLen) == (-1)) {
lprintf(LOG_ERR,
"Error in Write CD of SCSI_AMIDEF_CMD_SECTOR");
return (-1);
}
/* Write the data to hard disk */
if ((retVal = WriteSplitData(intf, ReqBuffer,
SCSI_AMIDEF_DATA_SECTOR,
ReqBuffLen, timeout)) != 0) {
lprintf(LOG_ERR,
"Error in WriteSplitData of SCSI_AMIDEF_DATA_SECTOR");
return (-1);
}
if (!timeout) {
return 0;
}
/* Read Status now */
waitretval = WaitForCommandCompletion(intf, pG2CDCmdHeader, timeout,
DataLen);
if (waitretval != 0) {
lprintf(LOG_ERR, "WaitForCommandComplete failed");
return (0 - waitretval);
} else {
lprintf(LOG_DEBUG, "WaitForCommandCompletion SUCCESS");
}
switch (pG2CDCmdHeader->Status) {
case ERR_SUCCESS:
*ResBuffLen = pG2CDCmdHeader->DataOutLen;
lprintf(LOG_DEBUG, "Before ReadSplitData %x", *ResBuffLen);
if (ReadSplitData(intf, (char *)ResBuffer,
SCSI_AMIDEF_DATA_SECTOR,
pG2CDCmdHeader->DataOutLen) != 0) {
lprintf(LOG_ERR,
"Err ReadSplitData SCSI_AMIDEF_DATA_SCTR");
return (-1);
}
/* Additional read to see verify there was not problem
* with the previous read
*/
DataLen = sizeof(CONFIG_CMD);
ReadCD(intf->fd, SCSI_AMIDEF_CMD_SECTOR,
(char *)(pG2CDCmdHeader), DataLen);
break;
case ERR_BIG_DATA:
lprintf(LOG_ERR, "Too much data");
break;
case ERR_NO_DATA:
lprintf(LOG_ERR, "Too little data");
break;
case ERR_UNSUPPORTED:
lprintf(LOG_ERR, "Unsupported command");
break;
default:
lprintf(LOG_ERR, "Unknown status");
}
return pG2CDCmdHeader->Status;
}
static struct ipmi_rs *
ipmi_usb_send_cmd(struct ipmi_intf *intf, struct ipmi_rq *req)
{
static struct ipmi_rs rsp;
long timeout = 20000;
uint8_t byRet = 0;
char ReqBuff[MAX_REQUEST_SIZE] = {0};
IPMIUSBRequest_T *pReqPkt = (IPMIUSBRequest_T *)ReqBuff;
int retries = 0;
/********** FORM IPMI PACKET *****************/
pReqPkt->byNetFnLUN = req->msg.netfn << 2;
pReqPkt->byNetFnLUN += req->msg.lun;
pReqPkt->byCmd = req->msg.cmd;
if (req->msg.data_len) {
memcpy(pReqPkt->byData, req->msg.data, req->msg.data_len);
}
/********** SEND DATA TO USB ******************/
while (retries < 3) {
retries++;
byRet = SendDataToUSBDriver(intf, ReqBuff,
2 + req->msg.data_len, rsp.data,
&rsp.data_len,timeout);
if (byRet == 0) {
break;
}
}
if (retries == 3) {
lprintf(LOG_ERR,
"Error while sending command using",
"SendDataToUSBDriver");
rsp.ccode = byRet;
return &rsp;
}
rsp.ccode = rsp.data[0];
/* Save response data for caller */
if ((rsp.ccode == 0) && (rsp.data_len > 0)) {
memmove(rsp.data, rsp.data + 1, rsp.data_len - 1);
rsp.data[rsp.data_len] = 0;
rsp.data_len -= 1;
}
return &rsp;
}