some playing around ...
[rfid/librfid.git] / gemtag / gemtag.c
index 28538c7..db4823e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) 2006 by Frank Zirkelbach <hackbard@hackdaworld.org>
+ *  (C) 2006 by 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 
 #include <usb.h>
 #include "gemtag.h"
 
-/* variables */
+int hexdump(unsigned char *data,int len) {
+       int i;
 
-struct gemtag_handle {
-       struct usb_dev_handle *handle;
-};
+       for(i=0;i<len;i++) printf("%02x ",data[i]);
+       printf("\n");
 
-/* functions */
+       return 0;
+}
 
-struct usb_device *find_device(unsigned short vendor, unsigned short device) {
+struct usb_device *find_device(unsigned short vendor,unsigned short device) {
        
        struct usb_bus *bus;
        struct usb_device *dev;
@@ -51,13 +52,112 @@ struct usb_device *find_device(unsigned short vendor, unsigned short device) {
        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_transcieve(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;
+       unsigned char buf[32];
+       u_int16_t crc,*crcptr;
+       int ret,size;
+
+       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>>8)|(tx_len<<8);
+       size=sizeof(struct gemtag_cmd_hdr);
+       memcpy(txbuf+size,tx,tx_len);
+       size+=tx_len;
+
+       /* crc check */
+       if(gh->capabilities&GEMTAG_CAP_CRC) {
+               crcptr=(u_int16_t *)(txbuf+size);
+               crc=gemtag_calc_crc(txbuf,size);
+               *crcptr=(crc>>8)|(crc<<8);
+               size+=2;
+       }
+
+       /* usb write */
+       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,buf,32,0);
+       if(ret<=0) {
+               perror("usb interrupt read");
+               return ret;
+       }
+       memcpy(rxbuf,buf,ret);
+       printf("(%02d) <- ",ret);
+       hexdump(rxbuf,ret);
+
+       *rx_len=buf[3]|(buf[4]<<8);
+       printf("debug: length according to header -> %d 0x%04x\n",
+              *rx_len,*rx_len);
+       size=*rx_len+5;
+
+       /* crc check */
+       if(gh->capabilities&GEMTAG_CAP_CRC) {
+               size=ret-2;
+               crcptr=(u_int16_t *)(rxbuf+size);
+               crc=gemtag_calc_crc(rxbuf,size);
+               if(((crc>>8)!=rxbuf[size+1])||((crc&0xff)!=rxbuf[size])) {
+                       printf("bad crc! (%04x)\n",crc);
+                       //return -BAD_CRC;
+               }
+       }
+
+       /* check sequence number */     
+       if(rxhdr->seq!=txhdr->seq) {
+               puts("transmitted/recieved sequence number do not match");
+               //return -SEQ_MISMATCH;
+       }
+
+       memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),*rx_len);
+
+       return 0;
+}
+
 struct gemtag_handle *gemtag_open(void) {
        struct usb_device *gemtag;
-       unsigned char rbuf[16];
-       unsigned int rlen;
-       unsigned int i,numconf;
-       unsigned int j,numint;
+       unsigned char rbuf[256];
+       unsigned int i,rlen;
        struct gemtag_handle *gh;
+       char info[64];
 
        rlen=sizeof(rbuf);
 
@@ -65,7 +165,7 @@ struct gemtag_handle *gemtag_open(void) {
        usb_find_busses();
        usb_find_devices();
 
-       gemtag=find_device(USB_VENDOR_GEMTAG, USB_DEVICE_X501);
+       gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501);
        if(!gemtag) return NULL;
 
        gh=malloc(sizeof(struct gemtag_handle));
@@ -73,23 +173,42 @@ struct gemtag_handle *gemtag_open(void) {
 
        memset(gh,0,sizeof(struct gemtag_handle));
 
-       numconf=gemtag->descriptor.bNumConfigurations;
-       printf("found gemtag, %u configurations\n",numconf);
-       for(i=0;i<numconf;i++) {
-               numint=gemtag->config[i].bNumInterfaces;
-               printf("config %u [nr %u] has %u interfaces\n",
-                      i,gemtag->config[i].bConfigurationValue,
-                      numint);
-               for(j=0;j<numint;j++) {
-                       printf("config %u interface %u has %u altsettings\n",
-                              i,j,gemtag->config[i].interface[j].num_altsetting);
-               }
-       }
-
        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, ");
+
+       // while(usb_set_altinterface(gh->handle,0))
+       //      printf("trying to set alt interface\n");
+       // printf("activated alt setting 0\n");
+
+       gh->capabilities|=GEMTAG_CAP_CRC;
+
+       gemtag_transcieve(gh,GEMTAG_CMD_GET_FW_VERSION,
+                         NULL,0,rbuf,&rlen);
+       gemtag_transcieve(gh,GEMTAG_CMD_GET_SERIAL_NUMBER,
+                         NULL,0,rbuf,&rlen);
+
+       return gh;
+
 out_free:
        free(gh);
        return NULL;