Project

General

Profile

Download (5.53 KB) Statistics
| Branch: | Tag: | Revision:
1
/* opcd_usb - Low-Level USB routines for OpenPCD USB protocol
2
 *
3
 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License version 2 
7
 *  as published by the Free Software Foundation
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program; if not, write to the Free Software
16
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 */
18

    
19
#include <errno.h>
20
#include <unistd.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include <time.h>
24
#include <sys/time.h>
25

    
26
#include <sys/types.h>
27

    
28
#include "ausb/ausb.h"
29
#include <openpcd.h>
30

    
31
#include "opcd_usb.h"
32

    
33
const char *
34
opcd_hexdump(const void *data, unsigned int len)
35
{
36
	static char string[65535];
37
	unsigned char *d = (unsigned char *) data;
38
	unsigned int i, left, ofs;
39

    
40
	string[0] = '\0';
41
	ofs = snprintf(string, sizeof(string)-1, "(%u): ", len);
42
	
43
	left = sizeof(string) - ofs;
44
	for (i = 0; len--; i += 3) {
45
		if (i >= sizeof(string) -4)
46
			break;
47
		snprintf(string+ofs+i, 4, " %02x", *d++);
48
	}
49
	string[sizeof(string)-1] = '\0';
50
	return string;
51
}
52

    
53
#define OPCD_OUT_EP	0x01
54
#define OPCD_IN_EP	0x82
55
#define OPCD_INT_EP	0x83
56

    
57
static struct usb_device *find_opcd_handle(int picc)
58
{
59
	struct usb_bus *bus;
60
	u_int16_t product_id;
61

    
62
	if (picc)
63
		product_id = OPENPICC_PRODUCT_ID;
64
	else
65
		product_id = OPENPCD_PRODUCT_ID;
66

    
67
	for (bus = usb_busses; bus; bus = bus->next) {
68
		struct usb_device *dev;
69
		for (dev = bus->devices; dev; dev = dev->next) {
70
			if (dev->descriptor.idVendor == OPENPCD_VENDOR_ID &&
71
			    dev->descriptor.idProduct == product_id)
72
				return dev;
73
		}
74
	}
75
	return NULL;
76
}
77

    
78
static void opcd_dump_hdr(struct openpcd_hdr *hdr)
79
{
80
	printf("IRQ: cmd=0x%02x, flags=0x%02x, reg=0x%02x, val=0x%02x\n",
81
		hdr->cmd, hdr->flags, hdr->reg, hdr->val);
82
}
83

    
84
static void handle_interrupt(struct usbdevfs_urb *uurb, void *userdata)
85
{
86
	ausb_dev_handle *ah;
87
	struct openpcd_hdr *opcdh;
88

    
89
	if (!uurb) {
90
		fprintf(stderr, "interrupt with no URB?!?\n");
91
		return;
92
	}
93

    
94
	ah = uurb->usercontext;
95

    
96
	opcdh = (struct openpcd_hdr *)uurb->buffer;
97
	opcd_dump_hdr(opcdh);
98

    
99
	if (ausb_submit_urb(ah, uurb))
100
		fprintf(stderr, "unable to resubmit interupt urb\n");
101
}
102

    
103
struct opcd_handle *opcd_init(int picc)
104
{
105
	struct opcd_handle *oh;
106
	struct usb_device *dev;
107

    
108
	oh = malloc(sizeof(*oh));
109
	if (!oh)
110
		return NULL;
111

    
112
	memset(oh, 0, sizeof(*oh));
113

    
114
	ausb_init();
115

    
116
	dev = find_opcd_handle(picc);
117
	if (!dev) {
118
		fprintf(stderr, "Cannot find OpenPCD device. "
119
			"Are you sure it is connected?\n");
120
		exit(1);
121
	}
122

    
123
	oh->hdl = ausb_open(dev);
124
	if (!oh->hdl) {
125
		fprintf(stderr, "Unable to open usb device: %s\n",
126
			usb_strerror());
127
		exit(1);
128
	}
129

    
130
	if (ausb_claim_interface(oh->hdl, 0) < 0) {
131
		fprintf(stderr, "Unable to claim usb interface "
132
			"1 of device: %s\n", usb_strerror());
133
		exit(1);
134
	}
135

    
136
	ausb_fill_int_urb(&oh->int_urb, OPCD_INT_EP, oh->int_buf, 
137
			  sizeof(oh->int_buf));
138
	if (ausb_register_callback(oh->hdl, USBDEVFS_URB_TYPE_INTERRUPT, 
139
				   handle_interrupt, oh)) {
140
		fprintf(stderr, "unable to submit interrupt urb");
141
		exit(1);
142
	}
143

    
144
	return oh;
145
}
146

    
147
void opcd_fini(struct opcd_handle *od)
148
{
149
	ausb_discard_urb(od->hdl, &od->int_urb);
150
	ausb_close(od->hdl);
151
}
152

    
153
int opcd_recv_reply(struct opcd_handle *od, char *buf, int len)
154
{
155
	int ret;
156
	memset(buf, 0, sizeof(buf));
157

    
158
	ret = ausb_bulk_read(od->hdl, OPCD_IN_EP, buf, len, 100000);
159

    
160
	if (ret < 0) {
161
		fprintf(stderr, "bulk_read returns %d(%s)\n", ret,
162
			usb_strerror());
163
		return ret;
164
	}
165

    
166
	//printf("RX: %s\n", opcd_hexdump(buf, ret));
167
	//printf("RX: %s\n", opcd_hexdump(buf, 48));
168
	//opcd_dump_hdr((struct openpcd_hdr *)buf);
169

    
170
	return ret;
171
}
172

    
173

    
174
int opcd_send_command(struct opcd_handle *od, u_int8_t cmd, 
175
		     u_int8_t reg, u_int8_t val, u_int16_t len,
176
		     const unsigned char *data)
177
{
178
	unsigned char buf[128];
179
	struct openpcd_hdr *ohdr = (struct openpcd_hdr *)buf;
180
	int cur = 0;
181
	int ret;
182

    
183
	memset(buf, 0, sizeof(buf));
184

    
185
	ohdr->cmd = cmd;
186
	ohdr->reg = reg;
187
	ohdr->val = val;
188
	ohdr->flags = OPENPCD_FLAG_RESPOND;
189
	if (data && len)
190
		memcpy(ohdr->data, data, len);
191
	
192
	cur = sizeof(*ohdr) + len;
193

    
194
	printf("TX: %s\n", opcd_hexdump(buf, cur));
195

    
196
	ret = ausb_bulk_write(od->hdl, OPCD_OUT_EP, buf, cur, 0);
197
	if (ret < 0) {
198
		fprintf(stderr, "bulk_write returns %d(%s)\n", ret,
199
			usb_strerror());
200
	}
201

    
202
	return ret;
203
}
204

    
205
int opcd_usbperf(struct opcd_handle *od, unsigned int frames)
206
{
207
	int i;
208
	char buf[256*64];
209
	struct timeval tv_start, tv_stop;
210
	unsigned int num_xfer = 0;
211
	unsigned int diff_msec;
212
	unsigned int transfers = 255;
213

    
214
	printf("starting DATA IN performance test (%u frames of 64 bytes)\n",
215
		frames);
216
	gettimeofday(&tv_start, NULL);
217
	opcd_send_command(od, OPENPCD_CMD_USBTEST_IN, transfers, frames, 0, NULL);
218
	for (i = 0; i < transfers; i++) {
219
		int ret;
220

    
221
		if (i < transfers - 1)
222
			opcd_send_command(od, OPENPCD_CMD_USBTEST_IN, transfers, frames, 0, NULL);
223
		ret = ausb_bulk_read(od->hdl, OPCD_IN_EP, buf, sizeof(buf), 0);
224
		if (ret < 0) {
225
			fprintf(stderr, "error receiving data in transaction\n");
226
			return ret;
227
		}
228
		num_xfer += ret;
229
	}
230
	gettimeofday(&tv_stop, NULL);
231
	diff_msec = (tv_stop.tv_sec - tv_start.tv_sec)*1000;
232
	diff_msec += (tv_stop.tv_usec - tv_start.tv_usec)/1000;
233

    
234
	printf("%u transfers (total %u bytes) in %u miliseconds => %u bytes/sec\n",
235
		i, num_xfer, diff_msec, (num_xfer*1000)/diff_msec);
236
	
237
	return 0;
238
}
(6-6/7)
Add picture from clipboard (Maximum size: 48.8 MB)