some playing around ...
[rfid/librfid.git] / gemtag / gemtag.c
1 /*
2  *  (C) 2006 by Frank Zirkelbach <hackbard@hackdaworld.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License version 2 
6  *  as published by the Free Software Foundation
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <errno.h>
23
24 #include <usb.h>
25 #include "gemtag.h"
26
27 int hexdump(unsigned char *data,int len) {
28         int i;
29
30         for(i=0;i<len;i++) printf("%02x ",data[i]);
31         printf("\n");
32
33         return 0;
34 }
35
36 struct usb_device *find_device(unsigned short vendor,unsigned short device) {
37         
38         struct usb_bus *bus;
39         struct usb_device *dev;
40
41         bus=usb_get_busses();
42         while(bus) {
43                 dev=bus->devices;
44                 while(dev) {
45                         if(dev->descriptor.idVendor==vendor &&
46                            dev->descriptor.idProduct==device)
47                                 return dev;
48                         dev=dev->next;
49                 }
50                 bus=bus->next;
51         }
52         return NULL;
53 }
54
55 u_int16_t gemtag_calc_crc(unsigned char *data,u_int16_t len) {
56
57         u_int16_t crc_polynom;
58         u_int16_t crc_preset;
59         u_int16_t crc;
60         int i,j;
61                 
62         crc_polynom=0x8408;
63         crc_preset=0xffff;
64         crc=0xffff;
65
66         for(i=0;i<len;i++) {
67                 crc^=data[i];
68                 for(j=0;j<8;j++) {
69                         if(crc&0x0001)
70                                 crc=(crc>>1)^crc_polynom;
71                         else
72                                 crc=(crc>>1);
73                 }
74         }
75         return crc;
76 }
77
78 int gemtag_transcieve(struct gemtag_handle *gh,unsigned char cmd,
79                          unsigned char *tx,unsigned int tx_len,
80                          unsigned char *rx,unsigned int *rx_len) {
81
82         unsigned char txbuf[256];
83         unsigned char rxbuf[256];
84         struct gemtag_cmd_hdr *txhdr;
85         struct gemtag_cmd_hdr *rxhdr;
86         unsigned char buf[32];
87         u_int16_t crc,*crcptr;
88         int ret,size;
89
90         txhdr=(struct gemtag_cmd_hdr *)txbuf;
91         rxhdr=(struct gemtag_cmd_hdr *)rxbuf;
92
93         txhdr->start=0xa5;
94         txhdr->seq=++(gh->seq);
95         txhdr->cmd=cmd;
96         txhdr->len=(tx_len>>8)|(tx_len<<8);
97         size=sizeof(struct gemtag_cmd_hdr);
98         memcpy(txbuf+size,tx,tx_len);
99         size+=tx_len;
100
101         /* crc check */
102         if(gh->capabilities&GEMTAG_CAP_CRC) {
103                 crcptr=(u_int16_t *)(txbuf+size);
104                 crc=gemtag_calc_crc(txbuf,size);
105                 *crcptr=(crc>>8)|(crc<<8);
106                 size+=2;
107         }
108
109         /* usb write */
110         printf("(%02d) -> ",size);
111         hexdump(txbuf,size);
112         ret=usb_interrupt_write(gh->handle,0x02,txbuf,size,0);
113         if(ret<=0) {
114                 perror("usb interrupt write");
115                 return ret;
116         }
117
118         /* usb read */
119         ret=usb_interrupt_read(gh->handle,0x81,buf,32,0);
120         if(ret<=0) {
121                 perror("usb interrupt read");
122                 return ret;
123         }
124         memcpy(rxbuf,buf,ret);
125         printf("(%02d) <- ",ret);
126         hexdump(rxbuf,ret);
127
128         *rx_len=buf[3]|(buf[4]<<8);
129         printf("debug: length according to header -> %d 0x%04x\n",
130                *rx_len,*rx_len);
131         size=*rx_len+5;
132
133         /* crc check */
134         if(gh->capabilities&GEMTAG_CAP_CRC) {
135                 size=ret-2;
136                 crcptr=(u_int16_t *)(rxbuf+size);
137                 crc=gemtag_calc_crc(rxbuf,size);
138                 if(((crc>>8)!=rxbuf[size+1])||((crc&0xff)!=rxbuf[size])) {
139                         printf("bad crc! (%04x)\n",crc);
140                         //return -BAD_CRC;
141                 }
142         }
143
144         /* check sequence number */     
145         if(rxhdr->seq!=txhdr->seq) {
146                 puts("transmitted/recieved sequence number do not match");
147                 //return -SEQ_MISMATCH;
148         }
149
150         memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),*rx_len);
151
152         return 0;
153 }
154
155 struct gemtag_handle *gemtag_open(void) {
156         struct usb_device *gemtag;
157         unsigned char rbuf[256];
158         unsigned int i,rlen;
159         struct gemtag_handle *gh;
160         char info[64];
161
162         rlen=sizeof(rbuf);
163
164         usb_init();
165         usb_find_busses();
166         usb_find_devices();
167
168         gemtag=find_device(USB_VENDOR_GEMTAG,USB_DEVICE_X501);
169         if(!gemtag) return NULL;
170
171         gh=malloc(sizeof(struct gemtag_handle));
172         if(!gh) return NULL;
173
174         memset(gh,0,sizeof(struct gemtag_handle));
175
176         gh->handle=usb_open(gemtag);
177         if(!gh->handle)
178                 goto out_free;
179
180         for(i=1;i<4;i++) {
181                 memset(info,0,sizeof(info));
182                 usb_get_string_simple(gh->handle,i,info,sizeof(info));
183                 printf("%s ",info);
184         }
185         printf("opened successfully\n");
186
187         if(usb_set_configuration(gh->handle,1)) {
188                 perror("set config");
189                 goto out_free;
190         }
191         printf("set configuration 1, ");
192
193         if(usb_claim_interface(gh->handle,0)) {
194                 perror("claim interface");
195                 goto out_free;
196         }
197         printf("claimed interface 0, ");
198
199         // while(usb_set_altinterface(gh->handle,0))
200         //      printf("trying to set alt interface\n");
201         // printf("activated alt setting 0\n");
202
203         gh->capabilities|=GEMTAG_CAP_CRC;
204
205         gemtag_transcieve(gh,GEMTAG_CMD_GET_FW_VERSION,
206                           NULL,0,rbuf,&rlen);
207         gemtag_transcieve(gh,GEMTAG_CMD_GET_SERIAL_NUMBER,
208                           NULL,0,rbuf,&rlen);
209
210         return gh;
211
212 out_free:
213         free(gh);
214         return NULL;
215 }
216         
217 int main(int argc, char **argv) {
218
219         struct gemtag_handle *gh;
220
221         gh=gemtag_open();
222
223         return 1;
224 }
225