minr modifications
[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         u_int16_t *crcptr;
87         int ret,size;
88
89         txhdr=(struct gemtag_cmd_hdr *)txbuf;
90         rxhdr=(struct gemtag_cmd_hdr *)rxbuf;
91
92         txhdr->start=0xa5;
93         txhdr->seq=++(gh->seq);
94         txhdr->cmd=cmd;
95         txhdr->len=htons(tx_len);
96         size=sizeof(struct gemtag_cmd_hdr);
97         memcpy(txbuf+size,tx,tx_len);
98
99         /* crc check */
100         if(gh->capabilities&GEMTAG_CAP_CRC) {
101                 size+=tx_len;
102                 crcptr=(u_int16_t *)(txbuf+size);
103                 *crcptr=htons(gemtag_calc_crc(txbuf,size));
104                 size+=2;
105         }
106
107         /* usb write */
108         printf("-> ");
109         hexdump(txbuf,size);
110         if(usb_clear_halt(gh->handle,0x02))
111                 perror("clear halt (out)");
112         ret=usb_bulk_write(gh->handle,0x02,txbuf,size,0);
113         if(ret<=0) {
114                 perror("usb bulk write");
115                 return ret;
116         }
117
118         /* usb read */
119         if(usb_clear_halt(gh->handle,0x81))
120                 perror("clear halt (in)");
121         ret=usb_bulk_read(gh->handle,0x81,rxbuf,sizeof(rxbuf),0);
122         size=ret;
123         if(ret<=0) {
124                 perror("usb bulk read");
125                 return ret;
126         }
127         printf("<- ");
128         hexdump(rxbuf,ret);
129         
130         if(rxhdr->seq!=txhdr->seq)
131                 puts("transmitted/recieved sequence number do not match");
132
133         /* crc check */
134         
135
136         *rx_len=ntohs(rxhdr->len);
137         memcpy(rx,rxbuf+sizeof(struct gemtag_cmd_hdr),
138                ret-sizeof(struct gemtag_cmd_hdr)+2);
139         hexdump(rxbuf,ret+2);
140
141         return 0;
142 }
143
144 struct gemtag_handle *gemtag_open(void) {
145         struct usb_device *gemtag;
146         unsigned char rbuf[16];
147         unsigned int rlen;
148         unsigned int i,numconf;
149         unsigned int j,numint;
150         unsigned int k,numalt;
151         struct gemtag_handle *gh;
152
153         rlen=sizeof(rbuf);
154
155         usb_init();
156         usb_find_busses();
157         usb_find_devices();
158
159         gemtag=find_device(USB_VENDOR_GEMTAG, USB_DEVICE_X501);
160         if(!gemtag) return NULL;
161
162         gh=malloc(sizeof(struct gemtag_handle));
163         if(!gh) return NULL;
164
165         memset(gh,0,sizeof(struct gemtag_handle));
166
167         numconf=gemtag->descriptor.bNumConfigurations;
168         printf("found gemtag (%02x/%02x), %u configuration(s)\n",
169                gemtag->descriptor.idVendor,
170                gemtag->descriptor.idProduct,numconf);
171         for(i=0;i<numconf;i++) {
172                 numint=gemtag->config[i].bNumInterfaces;
173                 printf("  config %u [nr %u] has %u interface(s)\n",
174                        i,gemtag->config[i].bConfigurationValue,
175                        numint);
176                 for(j=0;j<numint;j++) {
177                         numalt=gemtag->config[i].interface[j].num_altsetting;
178                         printf("    interface %u has %u altsetting(s): ",
179                                j,numalt);
180                         for(k=0;k<numalt;k++)
181                                 printf("%u ",
182                 gemtag->config[i].interface[j].altsetting[k].bAlternateSetting);
183                         printf("\n");
184                 }
185         }
186
187         gh->handle=usb_open(gemtag);
188         if(!gh->handle)
189                 goto out_free;
190         puts("usb_open successfull");
191
192         if(usb_set_configuration(gh->handle,1)) {
193                 perror("set config");
194                 goto out_free;
195         }
196         puts("configuration 1 successfully set");
197
198         if(usb_claim_interface(gh->handle,0)) {
199                 perror("claim interface");
200                 goto out_free;
201         }
202         puts("interface 0 claimed");
203
204         while(usb_set_altinterface(gh->handle,0))
205                 printf("trying to set alt interface\n");
206         puts("alt setting 0 selected");
207
208         gh->capabilities|=GEMTAG_CAP_CRC;
209
210         gemtag_transcieve(gh,GEMTAG_CMD_GET_FW_VERSION,
211                           NULL,0,rbuf,&rlen);
212
213         return gh;
214
215 out_free:
216         free(gh);
217         return NULL;
218 }
219         
220 int main(int argc, char **argv) {
221
222         struct gemtag_handle *gh;
223
224         gh=gemtag_open();
225
226         return 1;
227 }
228