USBasp 2005.04.21.
[pub/USBasp.git] / software / usbasp.c
1 #include "ac_cfg.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/time.h>
8 #include <unistd.h>
9
10 #include "avr.h"
11 #include "pgm.h"
12 #include "usbasp.h"
13
14 #ifdef HAVE_LIBUSB
15 #include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
16
17 extern char * progname;
18 extern int do_cycles;
19
20 static usb_dev_handle *usbhandle;
21
22 /*
23 * wrapper for usb_control_msg call
24 */
25 static int usbasp_transmit(unsigned char receive, unsigned char functionid,
26 unsigned char send[4], unsigned char * buffer, int buffersize)
27 {
28 int nbytes;
29 nbytes = usb_control_msg(usbhandle,
30 USB_TYPE_VENDOR | USB_RECIP_DEVICE | (receive << 7),
31 functionid,
32 (send[1] << 8) | send[0],
33 (send[3] << 8) | send[2],
34 buffer, buffersize,
35 5000);
36 if(nbytes < 0){
37 fprintf(stderr, "%s: error: usbasp_transmit: %s\n", progname, usb_strerror());
38 exit(1);
39 }
40
41 return nbytes;
42 }
43
44 static int usbasp_open(PROGRAMMER * pgm, char * port)
45 {
46 struct usb_bus *bus;
47 struct usb_device *dev = 0;
48
49 usb_init();
50 usb_find_busses();
51 usb_find_devices();
52 for(bus=usb_busses; bus; bus=bus->next){
53 for(dev=bus->devices; dev; dev=dev->next){
54 if(dev->descriptor.idVendor == USBDEV_VENDOR && dev->descriptor.idProduct == USBDEV_PRODUCT)
55 break;
56 }
57 if(dev)
58 break;
59 }
60 if(!dev){
61 fprintf(stderr, "%s: error: could not find USB device vendor=0x%x product=0x%x\n",
62 progname, USBDEV_VENDOR, USBDEV_PRODUCT);
63 exit(1);
64 }
65
66 usbhandle = usb_open(dev);
67 if(!usbhandle){
68 fprintf(stderr, "%s: error: opening usb device: %s\n",
69 progname, usb_strerror());
70 exit(1);
71 }
72
73 return 0;
74 }
75
76
77 static void usbasp_close(PROGRAMMER * pgm)
78 {
79 unsigned char temp[4];
80 memset(temp, 0, sizeof(temp));
81 usbasp_transmit(1, USBASP_FUNC_DISCONNECT, temp, temp, sizeof(temp));
82
83 usb_close(usbhandle);
84 }
85
86
87 static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p)
88 {
89
90 unsigned char temp[4];
91 memset(temp, 0, sizeof(temp));
92 usbasp_transmit(1, USBASP_FUNC_CONNECT, temp, temp, sizeof(temp));
93
94 usleep(100000);
95
96 pgm->program_enable(pgm, p);
97 return 0;
98 }
99
100 static void usbasp_disable(PROGRAMMER * pgm)
101 {
102 /* Do nothing. */
103
104 return;
105 }
106
107 static void usbasp_enable(PROGRAMMER * pgm)
108 {
109 /* Do nothing. */
110
111 return;
112 }
113
114 static void usbasp_display(PROGRAMMER * pgm, char * p)
115 {
116 return;
117 }
118
119
120 static int usbasp_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
121 unsigned char res[4])
122 {
123 int nbytes =
124 usbasp_transmit(1, USBASP_FUNC_TRANSMIT, cmd, res, sizeof(res));
125
126 if(nbytes != 4){
127 fprintf(stderr, "%s: error: wrong responds size\n",
128 progname);
129 return -1;
130 }
131
132 return 0;
133 }
134
135
136 static int usbasp_program_enable(PROGRAMMER * pgm, AVRPART * p)
137 {
138 unsigned char res[4];
139 unsigned char cmd[4];
140 memset(cmd, 0, sizeof(cmd));
141 memset(res, 0, sizeof(res));
142
143 cmd[0] = 0;
144
145 int nbytes =
146 usbasp_transmit(1, USBASP_FUNC_ENABLEPROG, cmd, res, sizeof(res));
147
148 if ((nbytes != 1) | (res[0] != 0)) {
149 fprintf(stderr, "%s: error: programm enable: target doesn't answer. %x \n",
150 progname, res[0]);
151 return -1;
152 }
153
154 return 0;
155 }
156
157
158 static int usbasp_chip_erase(PROGRAMMER * pgm, AVRPART * p)
159 {
160 unsigned char cmd[4];
161 unsigned char res[4];
162
163 if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
164 fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
165 p->desc);
166 return -1;
167 }
168
169 memset(cmd, 0, sizeof(cmd));
170
171 avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
172 pgm->cmd(pgm, cmd, res);
173 usleep(p->chip_erase_delay);
174 pgm->initialize(pgm, p);
175
176 return 0;
177 }
178
179
180 static int usbasp_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
181 int page_size, int n_bytes)
182 {
183 int n;
184 unsigned char cmd[4];
185 int address = 0;
186 int wbytes = n_bytes;
187 int blocksize;
188 unsigned char * buffer = m->buf;
189 int function;
190
191 if (strcmp(m->desc, "flash") == 0) {
192 function = USBASP_FUNC_READFLASH;
193 } else if (strcmp(m->desc, "eeprom") == 0) {
194 function = USBASP_FUNC_READEEPROM;
195 } else {
196 return -2;
197 }
198
199 while (wbytes) {
200 if (wbytes > USBASP_READBLOCKSIZE) {
201 blocksize = USBASP_READBLOCKSIZE;
202 wbytes -= USBASP_READBLOCKSIZE;
203 } else {
204 blocksize = wbytes;
205 wbytes = 0;
206 }
207
208 cmd[0] = address & 0xFF;
209 cmd[1] = address >> 8;
210
211 n = usbasp_transmit(1, function, cmd, buffer, blocksize);
212
213 if (n != blocksize) {
214 fprintf(stderr, "%s: error: wrong reading bytes %x\n",
215 progname, n);
216 exit(1);
217 }
218
219 buffer += blocksize;
220 address += blocksize;
221
222 report_progress (address, n_bytes, NULL);
223 }
224
225 return n_bytes;
226 }
227
228 static int usbasp_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
229 int page_size, int n_bytes)
230 {
231 int n;
232 unsigned char cmd[4];
233 int address = 0;
234 int wbytes = n_bytes;
235 int blocksize;
236 unsigned char * buffer = m->buf;
237 unsigned char blockflags = USBASP_BLOCKFLAG_FIRST;
238 int function;
239
240 if (strcmp(m->desc, "flash") == 0) {
241 function = USBASP_FUNC_WRITEFLASH;
242 } else if (strcmp(m->desc, "eeprom") == 0) {
243 function = USBASP_FUNC_WRITEEEPROM;
244 } else {
245 return -2;
246 }
247
248 while (wbytes) {
249 if (wbytes > USBASP_WRITEBLOCKSIZE) {
250 blocksize = USBASP_WRITEBLOCKSIZE;
251 wbytes -= USBASP_WRITEBLOCKSIZE;
252 } else {
253 blocksize = wbytes;
254 wbytes = 0;
255 blockflags |= USBASP_BLOCKFLAG_LAST;
256 }
257
258 cmd[0] = address & 0xFF;
259 cmd[1] = address >> 8;
260 cmd[2] = page_size & 0xFF;
261 cmd[3] = blockflags;
262 blockflags = 0;
263
264 n = usbasp_transmit(0, function, cmd, buffer, blocksize);
265
266 if (n != blocksize) {
267 fprintf(stderr, "%s: error: wrong count at writing %x\n",
268 progname, n);
269 exit(1);
270 }
271
272
273 buffer += blocksize;
274 address += blocksize;
275
276 report_progress (address, n_bytes, NULL);
277 }
278
279 return n_bytes;
280 }
281
282 void usbasp_initpgm(PROGRAMMER * pgm)
283 {
284 strcpy(pgm->type, "usbasp");
285
286 /*
287 * mandatory functions
288 */
289
290 pgm->initialize = usbasp_initialize;
291 pgm->display = usbasp_display;
292 pgm->enable = usbasp_enable;
293 pgm->disable = usbasp_disable;
294 pgm->program_enable = usbasp_program_enable;
295 pgm->chip_erase = usbasp_chip_erase;
296 pgm->cmd = usbasp_cmd;
297 pgm->open = usbasp_open;
298 pgm->close = usbasp_close;
299
300 /*
301 * optional functions
302 */
303
304 pgm->paged_write = usbasp_paged_write;
305 pgm->paged_load = usbasp_paged_load;
306
307 }
308
309
310 #else /* HAVE_LIBUSB */
311
312 extern char * progname;
313
314 static int usbasp_nousb_open (struct programmer_t *pgm, char * name)
315 {
316 fprintf(stderr, "%s: error: no usb support. please compile again with libusb installed.\n",
317 progname);
318
319 exit(1);
320 }
321
322 void usbasp_initpgm(PROGRAMMER * pgm)
323 {
324 strcpy(pgm->type, "usbasp");
325
326 pgm->open = usbasp_nousb_open;
327 }
328
329 #endif /* HAVE_LIBUSB */