ic35link/src/mgrproto.c

952 lines
27 KiB
C

/************************************************************************
* Copyright (C) 2001 Thomas Schulz *
* */
static char rcsid[] =
"$Id: mgrproto.c,v 1.17 2001/11/20 23:08:35 thosch Exp $"; /*
* *
* IC35 manager protocol *
* *
*************************************************************************
* *
* ??? is "fixme" mark: sections of code needing fixes *
* *
* IC35 manager protocol *
* Mcmdrsp send command-byte, get+check response-byte *
* Msendblk send datablock, test checksum, ack/retry *
* Mrecvblk receive datablock, test checksum, ack/retry *
* MMCard access protocol *
* MMCsend send MMCard command using Msendblk *
* MMCrecv receive MMCard response using Mrecvblk *
* MMCard commands *
* MMCgetstatus check if MMCard present / absent *
* MMCgetlabel get MMCard label *
* MMCdiropen open MMCard directory *
* MMCdirgetlen get number of entries in MMCard directory *
* MMCdirread read MMCard directory entry *
* MMCdirclose close MMCard directory *
* MMCfiledel delete MMCard file *
* MMCfileopen open MMCard file *
* MMCfilestat get MMCard file attributes *
* MMCfileread read block from MMCard file *
* MMCfilewrite write block to MMCard file *
* MMCfileclose close MMCard file *
* *
************************************************************************/
#include <stdlib.h> /* malloc(), .. */
#include <string.h> /* memcpy(), .. */
#include "util.h" /* ERR,OK, uchar, .. */
#include "comio.h" /* com_send(), .. */
#include "genproto.h" /* putxxx(),getxxx() .. */
#include "mgrproto.h"
NOTUSED(rcsid)
#define MAXRETRY 5 /* max.retries for manager protocol */
/* ==================================== */
/* IC35 manager protocol */
/* ==================================== */
/* send command-byte, get+check response-byte
* ------------------------------------------
*/
int
Mcmdrsp( uchar cmd, uchar rsp )
{
uchar rbyte;
int retry;
for ( retry = 0; retry < MAXRETRY; ++retry ) {
com_send( &cmd, sizeof(cmd) );
if ( com_recv( &rbyte, sizeof(rbyte) ) == sizeof(rbyte)
&& rbyte == rsp )
return OK;
}
return ERR;
}
/* local: send/receive block and ack or nak,retry
* ----------------------------------------------
* used by Msendblk(), Mrecvblk() for ack- or nak-handshake and retry,
* the trasnsmit function _sendblk(), _recvblk() is passed as function
* pointer 'pfxmit' and will set the appropriate timeout(s).
*/
static int
_xmitblk( uchar * data, size_t dlen, int pfxmit(uchar* data, size_t dlen) )
{
int old_tmo;
int retry;
int rval = ERR;
com_settimeout( old_tmo = com_settimeout( 0 ) );
for ( retry = 0; retry < MAXRETRY+1; ++retry ) {
rval = (*pfxmit)( data, dlen ); /* xmit data, recv csum */
if ( rval == dlen ) { /* datablock xmit OK */
if ( Mcmdrsp( MCMDposack, MRSPgotack ) != OK )
rval = ERR_acknak;
break;
} else if ( rval != ERR_recv /* bad checksum/length */
&& retry < MAXRETRY ) { /* and retries left */
if ( Mcmdrsp( MCMDnegack, MRSPgotack ) != OK ) {
rval = ERR_acknak;
break;
}
continue;
} else /* recv.err / timeout */
break; /* or out of retries */
}
com_settimeout( old_tmo );
return rval;
}
/* send block and ack/retry
* ------------------------
* send database block, receive checksum and test it, on success send
* acknowledge, receive ready response and return OK.
* on failure send nak and retry, after max.retries return ERR.
* -> (block of 'dlen' bytes)
* set timeout 10.0 sec
* <- cc_cc got them, checksum is cc_cc (arithmetic, LSB first)
* set timeout 3.0 sec
* -> 60 positive acknowledge
* <- A0 got ack
* on checksum mismatch send negative acknowledge:
* -> 62 negative acknowledge
* <- A0 got nak
* and restart send block.
* the long "(block of 'dlen' bytes)" must be sent with waiting!
*/
static int
_sendblk( uchar * data, size_t dlen )
{
uchar rcsum[2];
int lcsum;
ushort cksum;
int rval;
com_sendw( data, dlen ); /* -> data (with wait) */
com_settimeout( 10000 ); /* timeout 10.0 sec for chksum */
if ( (lcsum = com_recv( rcsum, sizeof(rcsum) )) /* <- checksum */
== sizeof(rcsum)
&& (cksum = chksum( data, dlen ))
== getword( rcsum ) ) {
rval = dlen;
} else {
if ( lcsum == sizeof(rcsum) ) { /* checksum mismatch */
LPRINTF(( L_NOISE, "_senddblk: chksum=%04X mismatch", cksum ));
rval = ERR_chksum;
} else /* recv.error / timeout */
rval = ERR_recv;
}
LPRINTF(( L_NOISE, "_sendblk(data,%d) = %d", dlen, rval ));
com_settimeout( 3000 ); /* timeout 3.0 sec ack/nak resp */
return rval;
}
int
Msendblk( uchar * data, size_t dlen )
{
return _xmitblk( data, dlen, _sendblk );
}
/* receive block and ack/retry
* ---------------------------
* receive data block, on success acknowledge and return OK.
* on failure send nak and retry, after max.retries return ERR.
* set timeout 2.0 sec
* <- (block of 'blen' bytes) cc_cc (arithmetic sum, LSB first)
* -> 60 positive acknowledge
* <- A0 got ack
* on mismatch of checksum or length, send negative acknowledge:
* -> 62 negative acknowledge
* <- A0 got nak
* and restart receive block.
*/
static int
_recvblk( uchar * buff, size_t blen )
{
uchar rcsum[2];
ushort cksum;
int lcsum;
int rval;
rcsum[0] = rcsum[1] = (uchar)0x00;
com_settimeout( 2000 ); /* timeout 2.0 sec for data,ack */
if ( (rval = com_recv( buff, blen )) >= 2 /* <- data */
&& (lcsum = com_recv( rcsum, sizeof(rcsum)) ) >= 0 ) { /* <- csum */
if ( lcsum == 1 ) {
rcsum[1] = buff[--rval]; /* take .. */
rcsum[0] = buff[--rval]; /* .. checksum bytes .. */
} else if ( lcsum == 0 ) {
rcsum[1] = rcsum[0]; /* .. from .. */
rcsum[0] = buff[--rval]; /* .. end of datablock */
}
if ( (cksum = chksum( buff, rval )) != getword( rcsum ) ) {
LPRINTF(( L_NOISE, "_recvblk: chksum=%04X mismatch", cksum ));
rval = ERR_chksum; /* checksum mismatch */
}
} else
rval = ERR_recv; /* too short for chksum */
LPRINTF(( L_NOISE, "_recvblk(buff,%d) = %d", blen, rval ));
return rval;
}
int
Mrecvblk( uchar * buff, size_t blen )
{
return _xmitblk( buff, blen, _recvblk );
}
/* ==================================== */
/* MMCard access protocol */
/* ==================================== */
/*
* protocol of MMCard operations
* MMCsend
* use timeout 0.5 sec
* -> 15 are you there ?
* <- 90 yes i am here !
* -> nn_nn expect nn_nn bytes from me
* <- E0 ok, send them
* sendretry:
* -> (block of nn_nn bytes)
* set timeout 10.0 sec
* <- cc_cc got them, checksum is cc_cc (arithmetic, LSB first)
* set timeout 3.0 sec
* -> 60 ack
* <- A0 got ack
* on checksum mismatch send negative acknowledge:
* -> 62 nak
* <- A0 got nak
* and restart at sendretry.
* the long "(block of nn_nn bytes)" must be sent with waiting!
* the blocklength nn_nn must be sent with wait before 1st byte!
* MMCrecv
* set timeout 5.0 sec
* <- nn_nn expect nn_nn bytes plus trailing checksum
* -> E0 ok, send them
* recvretry:
* <- (block of nn_nn bytes) cc_cc (arithmetic sum, LSB first)
* -> 60 ack
* <- A0 got ack
* on mismatch of checksum or length, send negative acknowledge:
* -> 62 nak
* <- A0 got nak
* and restart at recvretry.
*/
/* send MMCard command
* -------------------
*/
static int
MMCsend( uchar * sbuff, size_t slen )
{
uchar rchar;
uchar slbuff[2];
int rval;
if ( Mcmdrsp( MCMDmmcard, MRSPgotcmd ) == OK ) { /* -> 15 */
putword( slbuff, slen ); /* <- 90 */
com_sendw( slbuff, sizeof(slbuff) ); /* -> nn_nn (with wait) */
if ( com_recv( &rchar, 1 ) == 1 /* <- E0 */
&& rchar == MRSPgotlen ) {
rval = Msendblk( sbuff, slen ); /* send cmd, ack/retry */
if ( rval != slen ) /* Msendblk() bad length */
rval = ERR;
} else /* com_recv() MRSPgotlen failed */
rval = ERR;
} else /* Mcmdrsp() failed */
rval = ERR;
return rval;
}
/* receive MMCard response
* -----------------------
*/
static int
MMCrecv( uchar ** prbuff )
{
int old_tmo;
uchar rlbuff[2];
size_t rblen;
uchar rspgotlen = MRSPgotlen;
uchar * rbuff;
int rval;
old_tmo = com_settimeout( 5000 );
if ( (rval = com_recv( rlbuff, sizeof(rlbuff) )) == sizeof(rlbuff) ) {
rblen = getword( rlbuff ); /* <- nn nn */
if ( (rbuff = calloc( rblen, 1 )) != NULL ) {
com_send( &rspgotlen, 1 ); /* -> E0 */
rval = Mrecvblk( rbuff, rblen ); /* recv resp, ack/retry */
if ( rval == rblen ) {
*prbuff = rbuff; /* OK, buffer to caller */
} else {
free( rbuff ); /* Mrecvblk() bad length */
rval = ERR;
}
} else { /* calloc(rblen,1) failed */
LPRINTF(( L_ERROR, "MMCrecv: calloc(%d,1) failed", rblen ));
rval = ERR;
}
} else /* com_recv(rlbuff,) failed */
rval = ERR;
com_settimeout( old_tmo );
return rval;
}
/* ============================ */
/* MMCard commands */
/* ============================ */
/*
* MMCard command implementation
* the MMCard commands correspond to IC35 SDK API functions and are
* implemented as remote procedure calls: encode arguments to command
* PDU and send it to IC35, receive response PDU from IC35 and decode
* results from PDU.
* struct mcmdxxxx/mrspxxxx define the command/response PDU encoding.
* all MMCxxxx() functions work like:
* - _init*pdu() allocates the command PDU buffer and encodes the
* command code into it
* - encode MMCxxxx() function argument(s) into command PDU buffer
* (except fdstat argument)
* - _sendrecv() optionally encodes the MMCxxxx() fdstat argument
* into the command PDU for file/directory commands,
* sends the command PDU to IC35 with MMCsend() and releases it,
* receives the response PDU from IC35 with MMCrecv(),
* optionally decodes FILE_IDEN from response PDU back into the
* fdstat argument,
* and returns the status decoded from the response PDU.
* - decode MMCxxxx() result arguments
* - decode from the response PDU into MMCxxxx() result arguments,
* release response PDU buffer and return status from _sendrecv().
*/
/* MMCard command codes */ /* IC35 SDK API function: */
#define MMCMDgetstatus 0x20 /* 13.1 mInitialCard() */
#define MMCMDgetlabel 0x34 /* 13.4 mGetCardLabel() */
#define MMCMDdiropen 0x2A /* 13.14 mOpenDirectory() */
#define MMCMDdirgetlen 0x2B /* 13.15 mGetDirectorySubItemNum() */
#define MMCMDdirread 0x2C /* 13.16 mGetDirectorySubItem() */
#define MMCMDdirclose 0x2E /* 13.18 mCloseDirectory() */
#define MMCMDfileopen 0x22 /* 13.6 mOpenFile() */
#define MMCMDfilestat 0x26 /* 13.10 mGetFileInfo() */
#define MMCMDfilewrite 0x23 /* 13.8 mWriteToFile() */
#define MMCMDfileread 0x24 /* 13.9 mReadFromFile() */
#define MMCMDfileclose 0x27 /* 13.11 mCloseFile() */
#define MMCMDfiledel 0x28 /* 13.13 mDeleteFile() */
/* MMCard PDU definitions
* ----------------------
*/
/* getstatus, getlabel */
struct mcmdstatlbl { /* stat label */
char cmd[1]; /* 20 or 34 */
char mmcard[6]; /* "MMCard" */
char mmcnum[1]; /* "1" or "2" */
uchar zero[1]; /* 00 */
};
struct mrspstat {
uchar stat[2]; /* 01 00 or FF FF */
};
struct mrsplbl {
uchar stat[2]; /* 01 00 */
uchar zero[1]; /* 00 */
char label[8+1]; /* [MMClabel] 00 */
char reserved[11]; /* 20 20 00 00 00 00 00 00 00 00 48 */
};
/* diropen, fileopen */
struct mcmdfdopen { /* dopen fopen */
char cmd[1]; /* 2A or 22 */
uchar mode[2]; /* 01 00 */
uchar path[1]; /* [MMCardx\dir] 00 */
};
struct mrspfdopen {
uchar stat[2]; /* 01 00 */
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
};
/* dirglen, dirclose, filestat, fileclose */
struct mcmdfdstatcl { /* dglen dcls fstat fcls*/
char cmd[1]; /* 2B 2E 26 27 */
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar zero[1]; /* 00 */
};
struct mrspdirglen {
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar stat[2]; /* 01 00 */
uchar ndent[2]; /* nn_nn */
};
struct mrspfdclose {
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
};
/* dirread, fileread */
struct mcmdfdread { /* dread fread */
uchar cmd[1]; /* 2C or 24 */
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
union {
uchar index[2]; /* in_dx dir-index */
uchar blen[2]; /* nn_nn file-bufflen */
} u;
uchar zero[1]; /* 00 */
};
struct mrspfdstat {
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar stat[2]; /* 01 00 */
FILE_INFO dirent; /* (24 bytes FILE_INFO) */
};
struct mrspfileread {
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar stat[2]; /* 01 00 */
uchar rlen[2]; /* nn_nn */
uchar data[1]; /* filedata[nn_nn] */
};
/* filedel */
struct mcmdfiledel {
char cmd[1]; /* 28 */
uchar path[1]; /* [MMCardx\file] 00 */
};
/*resp mrspstat
*/
/* filewrite */
struct mcmdfilewrite {
uchar cmd[1]; /* 23 */
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar wlen[2]; /* nn_nn */
uchar data[1]; /* filedata[nn_nn] 00 */
};
struct mrspfilewrite {
uchar iden[FIDENSZ]; /* (27 bytes FILE_IDEN) */
uchar stat[2]; /* 01 00 */
};
union mcmdpdu { /* MMCard command PDU */
uchar cmd;
struct mcmdstatlbl status;
struct mcmdstatlbl label;
struct mcmdfdopen diropen;
struct mcmdfdstatcl dirglen;
struct mcmdfdread dirread;
struct mcmdfdstatcl dirclose;
struct mcmdfiledel filedel;
struct mcmdfdopen fileopen;
struct mcmdfdstatcl filestat;
struct mcmdfdread fileread;
struct mcmdfilewrite filewrite;
struct mcmdfdstatcl fileclose;
uchar data[1];
};
union mrsppdu { /* MMCard response PDU */
uchar stat[2];
struct mrspstat status;
struct mrsplbl label;
struct mrspfdopen diropen;
struct mrspdirglen dirglen;
struct mrspfdstat dirread;
struct mrspfdclose dirclose;
struct mrspstat filedel;
struct mrspfdopen fileopen;
struct mrspfdstat filestat;
struct mrspfileread fileread;
struct mrspfilewrite filewrite;
struct mrspfdclose fileclose;
uchar data[1];
};
union mmcpdu { /* generic MMCard PDU */
union mcmdpdu cmd;
union mrsppdu rsp;
};
/* MMCard PDU table
* ----------------
*/
#define SPDULENOF(type) sizeof( struct type )
#define FIDENOFFS(type) offsetof( struct type, iden )
#define RSTATOFFS(type) offsetof( struct type, stat )
#define NOFFS 0xFFFF
struct mpdudesc { /* MMCard PDU description */
uchar cmd; /* command code */
size_t slen; /* fixed length of PDU */
size_t sidenoffs; /* offset FILE_IDEN in cmd PDU */
size_t rstatoffs; /* offset status in resp.PDU */
size_t ridenoffs; /* offset FILE_IDEN in rsp PDU */
};
struct mpdudesc mmcpdutab[] = {
{ MMCMDgetstatus, SPDULENOF(mcmdstatlbl), NOFFS,
RSTATOFFS(mrspstat), NOFFS, },
{ MMCMDgetlabel, SPDULENOF(mcmdstatlbl), NOFFS,
RSTATOFFS(mrsplbl), NOFFS, },
{ MMCMDdiropen, SPDULENOF(mcmdfdopen), NOFFS,
RSTATOFFS(mrspfdopen), FIDENOFFS(mrspfdopen) },
{ MMCMDdirgetlen, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
RSTATOFFS(mrspdirglen), FIDENOFFS(mrspdirglen) },
{ MMCMDdirread, SPDULENOF(mcmdfdread), FIDENOFFS(mcmdfdread),
RSTATOFFS(mrspfdstat), FIDENOFFS(mrspfdstat) },
{ MMCMDdirclose, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
NOFFS, FIDENOFFS(mrspfdclose) },
{ MMCMDfileopen, SPDULENOF(mcmdfdopen), NOFFS,
RSTATOFFS(mrspfdopen), FIDENOFFS(mrspfdopen) },
{ MMCMDfilestat, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
RSTATOFFS(mrspfdstat), FIDENOFFS(mrspfdstat) },
{ MMCMDfilewrite, SPDULENOF(mcmdfilewrite), FIDENOFFS(mcmdfilewrite),
RSTATOFFS(mrspfilewrite), FIDENOFFS(mrspfilewrite) },
{ MMCMDfileread, SPDULENOF(mcmdfdread), FIDENOFFS(mcmdfdread),
RSTATOFFS(mrspfileread), FIDENOFFS(mrspfileread) },
{ MMCMDfileclose, SPDULENOF(mcmdfdstatcl), FIDENOFFS(mcmdfdstatcl),
NOFFS, FIDENOFFS(mrspfdclose), },
{ MMCMDfiledel, SPDULENOF(mcmdfiledel), NOFFS,
RSTATOFFS(mrspstat), NOFFS },
{ 0, 0, 0,
0, 0 }
};
/* init MMCard command PDU
* -----------------------
* lookup MMCard PDU description by command code
* allocate MMCard PDU buffer plus optionally variable length
* setup MMCard command code and return allocated PDU length
*/
static int /* init variable length PDU */
_initvpdu( uchar cmd, size_t varlen, union mmcpdu ** ppdu )
{
struct mpdudesc * pmpdu;
union mmcpdu * spdu;
size_t pdulen;
for ( pmpdu = mmcpdutab; pmpdu->slen != 0; ++pmpdu )
if ( pmpdu->cmd == cmd ) {
pdulen = pmpdu->slen + varlen;
if ( ppdu == NULL /* allocate PDU buffer */
|| (spdu = calloc( 1, pdulen )) == NULL )
break;
spdu->cmd.cmd = cmd; /* MMCard command code */
*ppdu = spdu;
return pdulen; /* length of PDU buffer */
}
return 0;
}
static int /* init fixe length PDU */
_initfpdu( uchar cmd, union mmcpdu ** ppdu )
{
return _initvpdu( cmd, 0, ppdu );
}
/* send MMCard command PDU, receive response PDU
* ---------------------------------------------
* optionally encode FILE_IDEN into command PDU
* send command PDU and release it
* receive response PDU, MMCrecv() will allocate it
* optionally decode FILE_IDEN and status from response PDU
*/
static long
_sendrecv( union mmcpdu ** ppdu, size_t * ppdulen, uchar * fdstat )
{
struct mpdudesc * pmpdu;
int rval;
for ( pmpdu = mmcpdutab; pmpdu->cmd != (*ppdu)->cmd.cmd; ++pmpdu )
if ( pmpdu->slen == 0 )
return ERR; /* PDU description not in table */
if ( pmpdu->sidenoffs != NOFFS && fdstat ) /* encode FILE_IDEN */
putbtxt( (*ppdu)->cmd.data + pmpdu->sidenoffs, fdstat, FIDENSZ );
rval = MMCsend( (*ppdu)->cmd.data, *ppdulen ); /* send command PDU */
free( *ppdu ); *ppdu = NULL; *ppdulen = 0; /* and release it */
if ( rval < 0 ) /* ERR, send failed */
return rval;
if ( (rval = MMCrecv( (uchar**)ppdu )) < 0 ) /* recv response PDU */
return rval; /* ERR, recv failed */
*ppdulen = rval; /* recv'd PDU length */
if ( pmpdu->ridenoffs != NOFFS && fdstat ) /* decode FILE_IDEN */
getbtxt( (*ppdu)->rsp.data + pmpdu->ridenoffs, fdstat, FIDENSZ );
if ( pmpdu->rstatoffs != NOFFS ) /* return status .. */
return getword( (uchar*)*ppdu + pmpdu->rstatoffs );/* from resp PDU */
else
return 0x0000; /* or no status */
}
/* convert FILE_INFO
* -----------------
* converts integer fields from IC35's to host's byte order
*/
static void
_cvtfinfo( FILE_INFO * pdudirent, FILE_INFO * hostdirent )
{
if ( pdudirent == NULL || hostdirent == NULL )
return;
getbtxt( (uchar*)pdudirent, (uchar*)hostdirent, sizeof(*hostdirent) );
hostdirent->ModifyTime = getword( (uchar*)&pdudirent->ModifyTime);
hostdirent->ModifyDate = getword( (uchar*)&pdudirent->ModifyDate);
hostdirent->FileSize = getdword( (uchar*)&pdudirent->FileSize );
}
/* MMCard general commands */
/* ======================= */
/* get MMCard status
* -----------------
* IC35 SDK API 13.1 mInitialCard()
* command: 20 "MMCard" [mmc_num] 00
* response: 01 00 MMCard present
* FF FF MMCard not detected
*/
long
MMCgetstatus( int mmcnum )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDgetstatus, &pdu )) <= 0 )
return ERR;
puttext( pdu->cmd.status.mmcard, "MMCard" );
putbyte( pdu->cmd.status.mmcnum, (char)('0'+mmcnum) );
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
return mstat;
free( pdu );
return mstat;
}
/* get MMCard label
* ----------------
* IC35 ADK API 13.4 mGetCardLabel()
* command: 34 "MMCard" [mmc_num] 00
* response: 01 00 00 label[8] 00 20 20 00 00 00 00 00 00 00 00 48
*/
long
MMCgetlabel( int mmcnum, char * plabel )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDgetlabel, &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
puttext( pdu->cmd.status.mmcard, "MMCard" );
putbyte( pdu->cmd.status.mmcnum, (char)('0'+mmcnum) );
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
return mstat;
/* decode rspargs */
gettext( pdu->rsp.label.label, plabel, strlen(pdu->rsp.label.label) );
free( pdu );
return mstat;
}
/* MMCard directory commands */
/* ========================= */
/* open MMC directory
* ------------------
* IC35 SDK API 13.14 mOpenDirectory()
* command: 2A 01 00 [MMCard1\path\to\dir] 00
* response: 01 00 fdiden[27]
*/
long
MMCdiropen( char * dirpath, uchar * fdstat )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initvpdu( MMCMDdiropen, strlen(dirpath), &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.diropen.mode, 0x0001 );
puttxt0( pdu->cmd.diropen.path, dirpath );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
free( pdu );
return mstat;
}
long
MMCdircreate( char * dirpath, uchar * fdstat )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initvpdu( MMCMDdiropen, strlen(dirpath), &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.diropen.mode, 0x0000 );
puttxt0( pdu->cmd.diropen.path, dirpath );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
free( pdu );
return mstat;
}
/* get num.of entries in MMCard directory
* --------------------------------------
* IC35 ADK API 13.15 mGetDirectorySubItemNum()
* command: 2B fdiden[27] 00
* response: fdiden[27] 01 00 nn_nn
*/
long
MMCdirgetlen( uchar * fdstat, ushort * pndent )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDdirgetlen, &pdu )) <= 0 )
return ERR;
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
/* decode rspargs */
*pndent = getword( pdu->rsp.dirglen.ndent );
free( pdu );
return mstat;
}
/* read MMC directory
* ------------------
* IC35 SDK API 13.16 mGetDirectorySubItem()
* command: 2C fdiden[27] in_dx 00
* response: fdiden[27] 01 00
* filename 00 ext 00 at ti_me_st_mp 00 00 fi_le_si_ze
*/
long
MMCdirread( uchar * fdstat, ushort index, FILE_INFO * pdirent )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDdirread, &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.dirread.u.index, index );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
/* decode rspargs */
_cvtfinfo( &pdu->rsp.dirread.dirent, pdirent );
free( pdu );
return mstat;
}
/* close MMC directory
* -------------------
* IC35 SDK API 13.18 mCloseDirectory()
* command: 2E fdiden[27] 00
* response: fdiden[27]
*/
long
MMCdirclose( uchar * fdstat )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDdirclose, &pdu )) <= 0 )
return ERR;
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
free( pdu );
return mstat;
}
/* MMCard file commands */
/* ==================== */
/* delete MMC file
* ---------------
* IC35 SDK API 13.13 mDeleteFile()
* command: 28 [MMCard1\path\to\file] 00
* response: 01 00
*/
long
MMCfiledel( char * filepath )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initvpdu( MMCMDfiledel, strlen(filepath), &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
puttxt0( pdu->cmd.filedel.path, filepath );
if ( (mstat = _sendrecv( &pdu, &pdulen, NULL )) < 0 )
return mstat;
free( pdu );
return mstat;
}
/* open MMC file
* -------------
* IC35 SDK API 13.6 mOpenFile()
* command: 22 01 00 [MMCard1\path\to\file] 00
* response: 01 00 fdiden[27]
*/
long
MMCfileopen( char * filepath, ushort mode, uchar * fdstat, ulong * psize )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initvpdu( MMCMDfileopen, strlen(filepath), &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.fileopen.mode, mode );
puttxt0( pdu->cmd.fileopen.path, filepath );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
/* decode rspargs */
*psize = getdword( pdu->rsp.fileopen.iden+14 );
free( pdu );
return mstat;
}
/* get MMC file status
* -------------------
* IC35 SDK API 13.10 mGetFileInfo()
* command: 26 fdiden[27] 00
* response: fdiden[27] 01 00
* filename 00 ext 00 at ti_me_st_mp 00 00 fi_le_si_ze
*/
long
MMCfilestat( uchar * fdstat, FILE_INFO * pdirent )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDfilestat, &pdu )) <= 0 )
return ERR;
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
/* decode rspargs */
_cvtfinfo( &pdu->rsp.filestat.dirent, pdirent );
free( pdu );
return mstat;
}
/* read data from MMC file
* -----------------------
* IC35 SDK API 13.9 mReadFormFile()
* command: 24 fdiden[27] nn_nn 00
* response: fdiden[27] 01 00 rr_rr
* <rr_rr bytes filedata>
*/
long
MMCfileread( uchar * fdstat, uchar * buff, ushort blen, ushort * prlen )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
size_t dlen;
if ( (pdulen = _initfpdu( MMCMDfileread, &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.fileread.u.blen, blen );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
/* decode rspargs */
*prlen = getword( pdu->rsp.fileread.rlen );
dlen = pdulen - offsetof(struct mrspfileread, data);
getbtxt( pdu->rsp.fileread.data, buff, dlen );
if ( dlen != *prlen )
LPRINTF(( L_WARN, "MMCfileread: rlen=%u, dlen=%u", *prlen, dlen ));
free( pdu );
return mstat;
}
/* write data to MMC file
* ----------------------
* IC35 SDK API 13.8 mWriteToFile()
* command: 23 fdiden[27] ww_ww
* <ww_ww bytes filedata> 00
* response: fdiden[27] 01 00
*/
long
MMCfilewrite( uchar * fdstat, uchar * data, ushort dlen )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initvpdu( MMCMDfilewrite, dlen, &pdu )) <= 0 )
return ERR;
/* encode cmdargs */
putword( pdu->cmd.filewrite.wlen, dlen );
putbtxt( pdu->cmd.filewrite.data, data, dlen );
putbyte( pdu->cmd.filewrite.data+dlen, 0x00 );
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
free( pdu );
return mstat;
}
/* close MMC file
* --------------
* IC35 SDK API 13.11 mCloseFile()
* command: 27 fdiden[27] 00
* response: fdiden[27]
*/
long
MMCfileclose( uchar * fdstat )
{
union mmcpdu * pdu;
int pdulen;
long mstat;
if ( (pdulen = _initfpdu( MMCMDfileclose, &pdu )) <= 0 )
return ERR;
if ( (mstat = _sendrecv( &pdu, &pdulen, fdstat )) < 0 )
return mstat;
free( pdu );
return mstat;
}