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