--- librfid-orig/gemtag/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ librfid/gemtag/Makefile	2006-03-10 18:41:22.000000000 +0100
@@ -0,0 +1,10 @@
+CC=gcc
+CFLAGS=-Wall
+
+all: gemtag
+
+gemtag: gemtag.o
+	$(CC) -lusb -o $@ $^
+
+clean:
+	rm -f gemtag *.o
--- librfid-orig/gemtag/gemtag.c	1970-01-01 01:00:00.000000000 +0100
+++ librfid/gemtag/gemtag.c	2006-03-23 15:30:27.000000000 +0100
@@ -0,0 +1,386 @@
+/*
+ *  (C) 2006 by Harald Welte <laforge@gnumonks.org>
+ *              Frank Zirkelbach <hackbard@hackdaworld.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 
+ *  as published by the Free Software Foundation
+ *
+ *  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 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <usb.h>
+#include "gemtag.h"
+
+int asciidump(unsigned char *data,int len) {
+
+	int i;
+
+	for(i=0;i<len;i++)
+		printf("%c",(data[i]>0x19)&&(data[i]<0x7f)?data[i]:'.');
+
+	return 0;
+}
+
+int hexdump(unsigned char *data,int len) {
+
+	int i;
+
+	for(i=0;i<len;i++) printf("%02x ",data[i]);
+
+	return 0;
+}
+
+struct usb_device *find_device(unsigned short vendor,unsigned short device) {
+	
+	struct usb_bus *bus;
+	struct usb_device *dev;
+
+	bus=usb_get_busses();
+	while(bus) {
+		dev=bus->devices;
+		while(dev) {
+			if(dev->descriptor.idVendor==vendor &&
+			   dev->descriptor.idProduct==device)
+				return dev;
+			dev=dev->next;
+		}
+		bus=bus->next;
+	}
+	return NULL;
+}
+
+u_int16_t gemtag_calc_crc(unsigned char *data,u_int16_t len) {
+
+	u_int16_t crc_polynom;
+	u_int16_t crc_preset;
+	u_int16_t crc;
+	int i,j;
+		
+	crc_polynom=0x8408;
+	crc_preset=0xffff;
+	crc=0xffff;
+
+	for(i=0;i<len;i++) {
+		crc^=data[i];
+		for(j=0;j<8;j++) {
+			if(crc&0x0001)
+				crc=(crc>>1)^crc_polynom;
+			else
+				crc=(crc>>1);
+		}
+	}
+	return crc;
+}
+
+int gemtag_transceive(struct gemtag_handle *gh,unsigned char cmd,
+                      unsigned char *tx,unsigned int tx_len,
+                      unsigned char *rx,unsigned int *rx_len) {
+
+	unsigned char txbuf[256];
+	unsigned char rxbuf[256];
+	struct gemtag_cmd_hdr *txhdr;
+	struct gemtag_cmd_hdr *rxhdr;
+	u_int16_t crc,*crcptr;
+	int i,ret,size,rest;
+
+	txhdr=(struct gemtag_cmd_hdr *)txbuf;
+	rxhdr=(struct gemtag_cmd_hdr *)rxbuf;
+
+	txhdr->start=0xa5;
+	txhdr->seq=++(gh->seq);
+	txhdr->cmd=cmd;
+ 	txhdr->len=tx_len;
+	size=sizeof(struct gemtag_cmd_hdr);
+	memcpy(txbuf+size,tx,tx_len);
+	size+=tx_len;
+
+	/* crc check */
+	if(gh->caps&GEMTAG_CAP_CRC) {
+		crcptr=(u_int16_t *)(txbuf+size);
+		crc=gemtag_calc_crc(txbuf,size);
+		//*crcptr=(crc>>8)|(crc<<8);
+		*crcptr=crc;
+		size+=2;
+	}
+
+	/* usb write */
+	if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) {
+		printf("(%02d) -> ",size);
+		hexdump(txbuf,size);
+	}
+	ret=usb_interrupt_write(gh->handle,0x02,txbuf,size,0);
+	if(ret<=0) {
+		perror("usb interrupt write");
+		return ret;
+	}
+
+	/* usb read */
+	ret=usb_interrupt_read(gh->handle,0x81,rxbuf,32,0);
+	if(ret<=0) {
+		perror("usb interrupt read");
+		return ret;
+	}
+	if(ret<5) {
+		if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT)
+			return -SHORT_ANSWER;
+	}
+
+	*rx_len=rxbuf[3]|(rxbuf[4]<<8);
+	size=*rx_len+sizeof(struct gemtag_cmd_hdr); 
+	if(gh->caps&GEMTAG_CAP_CRC) size+=2;
+
+	i=1;
+	rest=size-ret;
+	while(rest>=0) {
+		ret=usb_interrupt_read(gh->handle,0x81,rxbuf+i*32,32,0);
+		if(ret<=0) {
+			perror("usb interrupt read (missing bytes)");
+			return ret;
+		}
+		i++;
+		rest-=ret;
+	}
+
+	if(gh->caps&GEMTAG_CAP_VERB_TRANSMIT) {
+		printf("(%02d) <- ",size);
+		hexdump(rxbuf,size);
+	}
+
+	/* crc check */
+	if(gh->caps&GEMTAG_CAP_CRC) {
+		size-=2;
+		crcptr=(u_int16_t *)(rxbuf+size);
+		crc=gemtag_calc_crc(rxbuf,size);
+		if(((crc>>8)!=rxbuf[size+1])||((crc&0xff)!=rxbuf[size]))
+			return -BAD_CRC;
+	}
+
+	/* check sequence number */	
+	if(rxhdr->seq!=txhdr->seq) return -SEQ_MISMATCH;
+
+	/* check return code */
+	if(rxbuf[2]) return -CMD_FAILED;
+
+	memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),*rx_len);
+
+	return 0;
+}
+
+struct gemtag_handle *gemtag_open(void) {
+
+	struct usb_device *gemtag;
+	unsigned int i;
+	struct gemtag_handle *gh;
+	char info[64];
+
+	usb_init();
+	usb_find_busses();
+	usb_find_devices();
+
+	gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501);
+	if(!gemtag) return NULL;
+
+	gh=malloc(sizeof(struct gemtag_handle));
+	if(!gh) return NULL;
+
+	memset(gh,0,sizeof(struct gemtag_handle));
+
+	gh->handle=usb_open(gemtag);
+	if(!gh->handle)
+		goto out_free;
+
+	for(i=1;i<4;i++) {
+		memset(info,0,sizeof(info));
+		usb_get_string_simple(gh->handle,i,info,sizeof(info));
+		printf("%s ",info);
+	}
+	printf("opened successfully\n");
+
+	if(usb_set_configuration(gh->handle,1)) {
+		perror("set config");
+		goto out_free;
+	}
+	printf("set configuration 1, ");
+
+	if(usb_claim_interface(gh->handle,0)) {
+		perror("claim interface");
+		goto out_free;
+	}
+	printf("claimed interface 0\n");
+
+	/*
+	if(usb_set_altinterface(gh->handle,0))
+		perror("set alt interface");
+	printf("activated alt setting 0\n");
+	*/
+
+	return gh;
+
+out_free:
+	free(gh);
+	return NULL;
+}
+
+int gemtag_close(struct gemtag_handle *gh) {
+
+	if(gh->handle) usb_close(gh->handle);
+	if(gh) free(gh);
+
+	return 0;
+}
+
+int gemtag_transform_mifare_key(struct gemtag_handle *gh,
+                         unsigned char *key6,unsigned char *key12) {
+
+	unsigned int len;
+
+	gemtag_transceive(gh,GEMTAG_CMD_HOST_CODE_KEY,key6,6,key12,&len);
+
+	return 0;
+}
+
+int gemtag_auth_e2(struct gemtag_handle *gh,unsigned char authmode,
+                   int sector,unsigned char *key6) {
+
+	unsigned char buf[32];
+	unsigned int len,ret;
+
+	/* memory layout (sector/block) ? */
+
+	buf[0]=authmode;
+	buf[1]=0;
+	memcpy(buf+2,key6,6);
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PCD_LOAD_KEY_E2,buf,8,buf,&len);
+	if(ret) return -LOAD_E2_FAILED;
+
+	buf[0]=authmode;
+	memcpy(buf+1,gh->serial,4);
+	buf[5]=0;
+	buf[6]=sector;
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_E2,buf,7,buf,&len);
+	if(ret) return -AUTH_E2_FAILED;
+
+	return 0;
+
+}
+
+int gemtag_auth_mifare_key(struct gemtag_handle *gh,
+                           unsigned char *key6,int sector) {
+
+	unsigned char key12[12];	
+	unsigned char buf[32];
+	unsigned int len,ret;
+
+	gemtag_transform_mifare_key(gh,key6,key12);
+	                     
+	buf[0]=GEMTAG_PICC_AUTHENT1A; 	/* auth mode */
+	memcpy(buf+1,gh->serial,4);	/* sreial */
+	memcpy(buf+5,key12,12); 	/* transformed key */
+	buf[17]=sector; 		/* sector */
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_AUTH_KEY,buf,18,
+	                      buf,&len);
+	if(ret) return -AUTH_FAILED;
+
+	return 0;
+}
+
+int gemtag_read16(struct gemtag_handle *gh,int sector,unsigned char *data) {
+
+	unsigned char buf[32];
+	int len,ret;
+
+	buf[0]=sector;
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_READ,buf,1,data,&len);
+	if(ret) return -READ_FAILED;
+
+	return 0;
+}
+
+int gemtag_write16(struct gemtag_handle *gh,int sector,unsigned char *data) {
+
+	unsigned char buf[32];
+	int ret,len;
+
+	buf[0]=sector;
+	memcpy(buf+1,data,16);
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_WRITE,buf,17,buf,&len);
+	if(ret) return -WRITE_FAILED;
+
+	return 0;
+}
+
+int gemtag_select_picc(struct gemtag_handle *gh) {
+
+	unsigned char buf[16];
+	unsigned int len;
+	int ret;
+
+	buf[0]=GEMTAG_PICC_REQIDL;
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_REQUEST,buf,1,buf,&len);
+	if(ret) return -NO_PICC;
+
+	buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
+	memset(buf+1,0,5);
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_ANTICOLL,buf,6,buf,&len);
+	if(ret) return -NO_PICC;
+	memcpy(gh->serial,buf,4);
+
+	buf[0]=GEMTAG_PICC_STD_SELECT_CODE;
+	memcpy(buf+1,gh->serial,4);
+	ret=gemtag_transceive(gh,GEMTAG_CMD_PICC_CASC_SELECT,buf,5,buf,&len);
+	if(ret) return -PICC_SELECT_ERROR;
+
+	return 0;
+}
+
+int main(int argc, char **argv) {
+
+	struct gemtag_handle *gh;
+	unsigned char buf[256];
+	unsigned char key6[6];
+	int i,ret;
+
+	gh=gemtag_open();
+
+	gh->caps|=GEMTAG_CAP_CRC;
+	//gh->caps|=GEMTAG_CAP_VERB_TRANSMIT;
+
+	if(gemtag_select_picc(gh)) {
+		printf("no card found!\n");
+		return -NO_PICC;
+	}
+
+	memset(key6,0xff,6);
+	printf("\nreading sectors ... (serial: %02x %02x %02x %02x)\n\n",
+	       gh->serial[3],gh->serial[2],gh->serial[1],gh->serial[0]);
+	i=0;
+	while(!gemtag_auth_mifare_key(gh,key6,i)) {
+		ret=gemtag_read16(gh,i,buf);
+		printf("%02x: ",i);
+		hexdump(buf,16);
+		printf(" | ");
+		asciidump(buf,16);
+		printf("\n");
+		i+=1;
+	}
+	printf("\n");
+
+	gemtag_close(gh);
+
+	return 0;
+}
+
--- librfid-orig/gemtag/gemtag.h	1970-01-01 01:00:00.000000000 +0100
+++ librfid/gemtag/gemtag.h	2006-03-23 15:23:44.000000000 +0100
@@ -0,0 +1,148 @@
+/*
+ * (C) 2006 by Harald Welte <laforge@gnumonks.org>
+ *             Frank Zirkelbach <hackbard@hackdaworld.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 
+ *  as published by the Free Software Foundation
+ *
+ *  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 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 _GEMTAG_H
+#define _GEMTAG_H
+
+#define USB_VENDOR_GEMTAG	0x1394
+#define USB_DEVICE_X501		0x0501
+
+struct gemtag_handle {
+	struct usb_dev_handle *handle;
+	unsigned char seq;
+	unsigned char caps;
+	unsigned char serial[4];
+};
+
+#define GEMTAG_CAP_CRC			0x01
+#define GEMTAG_CAP_VERB_TRANSMIT	0x02
+
+struct gemtag_cmd_hdr {
+	unsigned char start;
+	unsigned char seq;
+	unsigned char cmd;
+	u_int16_t len;
+} __attribute__ ((packed));
+
+#define BAD_CRC				0x01
+#define SEQ_MISMATCH			0x02
+#define SHORT_ANSWER			0x03
+#define CMD_FAILED			0x04
+#define AUTH_FAILED			0x05
+#define READ_FAILED			0x06
+#define WRITE_FAILED			0x07
+#define NO_PICC				0x08
+#define PICC_SELECT_ERROR		0x09
+#define LOAD_E2_FAILED			0x0a
+#define AUTH_E2_FAILED			0x0b
+
+/* gemtag commands */
+
+#define GEMTAG_CMD_PCD_CONFIG		0x10
+#define GEMTAG_CMD_PICC_ANTICOLL	0x12
+#define GEMTAG_CMD_PICC_SELECT		0x13
+
+#define GEMTAG_CMD_PICC_AUTH		0x14
+#define GEMTAG_CMD_PICC_AUTH_E2		0x15
+#define GEMTAG_CMD_HOST_CODE_KEY	0x16
+#define GEMTAG_CMD_PCD_LOAD_KEY_E2	0x17
+#define GEMTAG_CMD_PICC_AUTH_KEY	0x18
+#define GEMTAG_PICC_AUTHENT1A		0x60
+#define GEMTAG_PICC_AUTHENT1B		0x61
+
+#define GEMTAG_CMD_PICC_READ		0x19
+#define GEMTAG_CMD_PICC_WRITE		0x1a
+#define GEMTAG_CMD_PICC_VALUE		0x1b
+#define GEMTAG_CMD_PICC_VALUE_DEBIT	0x1c
+#define GEMTAG_CMD_PICC_HALT		0x1d
+#define GEMTAG_CMD_PICC_WRITE4		0x1e
+#define GEMTAG_CMD_COMMON_WRITE		0x1f
+#define GEMTAG_CMD_PCD_RF_RESET		0x20
+#define GEMTAG_CMD_GET_SERIAL_NUMBER	0x22
+#define GEMTAG_CMD_PCD_READ_E2		0x23
+#define GEMTAG_CMD_PCD_WRITE_E2		0x24
+#define GEMTAG_CMD_PICC_COMMON_READ	0x28
+#define GEMTAG_PICC_DECREMENT		0xc0
+#define GEMTAG_PICC_INCREMENT		0xc1
+#define GEMTAG_PICC_RESTORE		0xc2
+#define GEMTAG_PICC_READ16		0x30
+#define GEMTAG_PICC_WRITE16		0xa0
+#define GEMTAG_PICC_WRITE4		0xa2
+
+#define GEMTAG_CMD_PCD_SET_TMO		0x27
+
+#define GEMTAG_CMD_PICC_REQUEST		0x40
+#define GEMTAG_CMD_PICC_CASC_ANTICOLL	0x41
+#define GEMTAG_CMD_PICC_CASC_SELECT	0x42
+#define GEMTAG_PICC_STD_SELECT_CODE	0x93
+#define GEMTAG_PICC_CASC_LEVEL1		0x95
+#define GEMTAG_PICC_CASC_LEVEL2		0x97
+/* from another source (mac gemtag tool) ... */
+#define GEMTAG_PICC_CASC_L1		0x93
+#define GEMTAG_PICC_CASC_L2		0x92
+#define GEMTAG_PICC_CASC_L3		0x94
+#define GEMTAG_PICC_CASC_L4		0x98
+#define GEMTAG_PICC_CASC_L5		0x95
+#define GEMTAG_PICC_CASC_L6		0x97
+
+#define GEMTAG_CMD_PICC_ACTIVATE_IDLE	0x43
+#define GEMTAG_CMD_PICC_ACTIVATE_WAKEUP	0x44
+#define GEMTAG_CMD_SET_DFLT_ATTRIBUTES	0x45
+#define GEMTAG_CMD_SET_ATTRIBUTES	0x46
+#define GEMTAG_CMD_PICC_EXCHANGE_BLOCK	0x48
+#define GEMTAG_PICC_REQIDL		0x26
+#define GEMTAG_PICC_REQALL		0x52
+
+#define GEMTAG_CMD_SWITCH_LED		0x60
+#define GEMTAG_LED_OFF			0x00
+#define GEMTAG_LED_ON			0x01
+
+#define GEMTAG_CMD_GET_FW_VERSION	0x63
+#define GEMTAG_CMD_GET_RIC_VERSION	0x64
+#define GEMTAG_CMD_SET_DEFAULT_BAUDRATE	0x81
+#define GEMTAG_CMD_SET_ONLINE_BAUDRATE	0x82
+#define GEMTAG_CMD_SET_CPU_TIMEOUT	0x88
+
+#define GEMTAG_CMD_DETECT_CARD		0x92
+#define GEMTAG_CMD_DETECT_ISO15693_CARD	0x93
+#define GEMTAG_CMD_PPS_REQUEST		0xa0
+#define GEMTAG_CMD_DESELECT		0xa1
+
+
+/* function prototypes */
+
+int asciidump(unsigned char *data,int len);
+int hexdump(unsigned char *data,int len);
+struct usb_device *find_device(unsigned short vendor,unsigned short device);
+u_int16_t gemtag_calc_crc(unsigned char *data,u_int16_t len);
+int gemtag_transceive(struct gemtag_handle *gh,unsigned char cmd,
+                      unsigned char *tx,unsigned int tx_len,
+                      unsigned char *rx,unsigned int *rx_len);
+struct gemtag_handle *gemtag_open(void);
+int gemtag_close(struct gemtag_handle *gh);
+int gemtag_transform_mifare_key(struct gemtag_handle *gh,
+                                unsigned char *key6,unsigned char *key12);
+int gemtag_auth_e2(struct gemtag_handle *gh,unsigned char authmode,
+                   int sector,unsigned char *key6);
+int gemtag_auth_mifare_key(struct gemtag_handle *gh,
+                           unsigned char *key6,int sector);
+int gemtag_read16(struct gemtag_handle *gh,int sector,unsigned char *data);
+int gemtag_write16(struct gemtag_handle *gh,int sector,unsigned char *data);
+int gemtag_select_picc(struct gemtag_handle *gh);
+
+#endif
