/***************************************************************************
 *            protocol.h
 *
 *  Wed May 12 08:28:55 2004
 *  Copyright  2004  Stanislav Brabec
 *  utx@penguin.cz
 ****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICUware Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef _PROTOCOL_H
#define _PROTOCOL_H

#include <stdint.h>
#include <utils.h>

#include "mltusb.h"
#include "mltrec.h"

#define MLTHDR_DEFINE_FUNCTION(name, offset, bizsize)\
static inline uint ## bizsize ## _t mlthdr_get_ ## name (uint8_t *mlthdr)\
{\
  return le ## bizsize ## _to_cpu (*((uint ## bizsize ## _t *)(mlthdr + offset)));\
}\
\
static inline void mlthdr_set_ ## name (uint8_t *mlthdr, uint ## bizsize ## _t name)\
{\
  *((uint ## bizsize ## _t *)(mlthdr + offset)) = cpu_to_le ## bizsize (name);\
}

#define MLTHDR_DEFINE_FUNCTION8(name, offset)\
static inline uint8_t mlthdr_get_ ## name (uint8_t *mlthdr)\
{\
  return *((uint8_t *)(mlthdr + offset));	\
}\
\
static inline void mlthdr_set_ ## name (uint8_t *mlthdr, uint8_t name)\
{\
  *((uint8_t *)(mlthdr + offset)) = name;\
}

#define MLTHDR_DEFINE_POINTER(name, offset, bizsize)\
static inline uint ## bizsize ## _t * mlthdr_ ## name (uint8_t *mlthdr)\
{\
  return (uint ## bizsize ## _t *)(mlthdr + offset);\
}

static inline uint32_t mlthdr_get (uint8_t *mlthdr, int offset)
{
  return *((uint32_t *)(mlthdr + offset));
}

/* generic commands */
MLTHDR_DEFINE_FUNCTION (size, 0x00, 32)
MLTHDR_DEFINE_FUNCTION (command, 0x04, 16)
MLTHDR_DEFINE_FUNCTION (extcmd, 0x06, 16)
MLTHDR_DEFINE_FUNCTION (serial, 0x08, 32)

MLTHDR_DEFINE_FUNCTION (extval, 0x0c, 32)
MLTHDR_DEFINE_FUNCTION (extval1, 0x0c, 16)
MLTHDR_DEFINE_FUNCTION (extval2, 0x0e, 16)

MLTHDR_DEFINE_FUNCTION (esize, 0x10, 32)

MLTHDR_DEFINE_FUNCTION (ext0, 0x10, 32)
MLTHDR_DEFINE_FUNCTION (ext1, 0x14, 32)
MLTHDR_DEFINE_FUNCTION (ext2, 0x18, 32)
MLTHDR_DEFINE_FUNCTION (ext3, 0x1c, 32)
MLTHDR_DEFINE_FUNCTION (ext4, 0x20, 32)
MLTHDR_DEFINE_FUNCTION (ext5, 0x24, 32)
MLTHDR_DEFINE_FUNCTION (ext6, 0x28, 32)
MLTHDR_DEFINE_FUNCTION (ext7, 0x2c, 32)
MLTHDR_DEFINE_FUNCTION (ext8, 0x30, 32)

MLTHDR_DEFINE_FUNCTION (ew0, 0x10, 16)
MLTHDR_DEFINE_FUNCTION (ew1, 0x12, 16)
MLTHDR_DEFINE_FUNCTION (ew2, 0x14, 16)
MLTHDR_DEFINE_FUNCTION (ew3, 0x16, 16)
MLTHDR_DEFINE_FUNCTION (ew4, 0x18, 16)
MLTHDR_DEFINE_FUNCTION (ew5, 0x1a, 16)
MLTHDR_DEFINE_FUNCTION (ew6, 0x1c, 16)
MLTHDR_DEFINE_FUNCTION (ew7, 0x1e, 16)
MLTHDR_DEFINE_FUNCTION (ew8, 0x20, 16)
MLTHDR_DEFINE_FUNCTION (ew9, 0x22, 16)

int mltprot_bulk_read (mltrec_device *mltdev, char *bytes, int size);
int mltprot_bulk_write (mltrec_device * mltdev, char *buf, int size);
int mltprot_write_header (mltrec_device * mltdev,
			 uint8_t * hdr, uint32_t size);
uint8_t *mltprot_read (mltrec_device * mltdev);
uint8_t *mltprot_read_data (mltrec_device * mltdev, uint8_t *data, int size);

void mltprot_enqueue (mltrec_device * mltdev, uint8_t *hdr, uint32_t size, uint16_t command, uint32_t serial,
		 mltprot_complete_callback callback, void *user_data);
struct mltprot_queue_item *mltprot_dequeue (mltrec_device * mltdev, uint32_t serial);

void mltprot_submit_command (mltrec_device * mltdev, mltprot_header * hdr,
			uint16_t command, uint32_t size,
			mltprot_complete_callback callback, void *user_data);

//void mltprot_complete (mltrec_device * mltdev, uint16_t command_to_complete);

/* FIXME: should be differently written */
void
mltprot_default_complete (mltrec_device * mltdev, mltprot_header *hdr, void *user_data);

void mltprot_complete_callback_set (mltrec_device * mltdev,
				    mltprot_complete_callback complete_callback, void *user_data);

#endif /* _PROTOCOL_H */

