Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ezusb_loader.cpp

00001 /*
00002  * Copyright (C) 1999 Dirk-Willem van Gulik, dirkx@webweaving.org
00003  *      WebWeaving Consultancy, All rights reserved.
00004  *
00005  * Original version for FreeBSD; Changes for Linux by Brad Hards,
00006  * brad.hards@dao.defence.gov.au. See '#ifdef BSD'.
00007  *
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY WEBWEAVING AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL WEBWEAVING OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * $FreeBSD$
00031  *
00032  * This downloader should work with all with all USB-EZ Anchorchips which
00033  * have on board ram; i.e. the AN21y1, AN21y5 and AN21y6QC series. Where y
00034  * is the log2 of the internal memory size (i.e. aAN2146QC has 2^64=16kByte
00035  * of ram.)
00036  *
00037  * It has however only been tested; and written specifically for the
00038  * ActiveWire Inc. USB board. See
00039  *      http://www.activewireinc.com
00040  *
00041  * Anchorchips has excelent documentation on line at
00042  *      http://www.anchorchips.com
00043  */
00044 /*
00045         This file is part of PXA250 USB JTAG controller.
00046 
00047         It has been heavily modified by Jean-Marc Koller
00048         and then by Julien Pilet <julien.pilet@epfl.ch> and
00049         Stephane Magnenat <stephane.magnenat@epfl.ch>
00050 
00051 */
00061 #include <string.h>
00062 #include <stdlib.h>
00063 #include <stdio.h>
00064 #include <unistd.h>
00065 #include <errno.h>
00066 
00067 #ifdef HAVE_GETOPT_LONG
00068 #include <getopt.h>
00069 #endif
00070 
00071 #include "ezusb_loader.h"
00072 #include "jtag_order.h"
00073 #include "jtag.h"
00074 #include "filemanager.h"
00075 
00076 
00077 EzUSB::EzUSB(const char *filename)
00078 {
00079         idVendor=0x547;
00080         idProduct=0x2131;
00081         if (filename)
00082         {
00083                 strncpy(this->filename, filename, 1024);
00084                 this->filename[sizeof(this->filename)-1]=0;
00085         }
00086         else
00087                 this->filename[0]=0;
00088         devHandle=NULL;
00089 };
00090 
00091 EzUSB::~EzUSB(void)
00092 {
00093         forceClose();
00094 }
00095 
00096 void EzUSB::forceClose(void)
00097 {
00098         if (devHandle)
00099         {
00100                 //usb_release_interface(devHandle, 0);
00101                 //usb_close(devHandle);
00102                 //printf("Closing device\n");
00103                 printf("USB : Reseting device\n");
00104                 usb_reset(devHandle);
00105         }
00106 }
00107 
00108 void EzUSB::parseCmdLine(int argc, char *argv[])
00109 {
00110 #ifdef HAVE_GETOPT_LONG
00111         int ch;
00112 
00113         struct option longOptions[] =
00114         {
00115                 {"idvendor", 1, 0, 'v'},
00116                 {"idproduct", 1, 0, 'p'},
00117                 {"filaname", 1, 0, 'f'},
00118                 {0, 0, 0, 0}
00119         };
00120 
00121         // handle the arguments
00122         while((ch = getopt_long(argc, argv, "vpf", longOptions, NULL)) != -1)
00123         {
00124                 switch (ch)
00125                 {
00126                         case 'v':
00127                                 idVendor=atoi(optarg);
00128                                 break;
00129                         case 'p':
00130                                 idProduct=atoi(optarg);
00131                                 break;
00132                         case 'f':
00133                                 if (optarg)
00134                                 {
00135                                         strncpy(filename, optarg, 1024);
00136                                         filename[sizeof(filename)-1]=0;
00137                                 }
00138                                 break;
00139                         default:
00140                                 break;
00141                 };
00142         }
00143 #else
00144         if (argc>1)
00145                 fprintf(stderr, "WARNING ignoring arguments for EzUSB"
00146                                 " initialisation: getopt_long is not available !\n");
00147 #endif
00148 }
00149 
00150 bool EzUSB::findDevice(void)
00151 {
00152         struct usb_bus* bus;
00153         struct usb_device* device;
00154 
00155         if (devHandle)
00156         {
00157                 // TODO : libusb doesn't seems to work here, check on other plateform
00158                 /*printf("USB : Device already exists, reloading...\n");
00159                 usb_resetep(devHandle, 2);
00160                 usb_release_interface( devHandle, 0);
00161                 //return true;*/
00162                 //usb_reset(devHandle);
00163         }
00164         usb_init();
00165         usb_find_busses();
00166         usb_find_devices();
00167 
00168         printf("USB : Enumerating USB\n");
00169         for( bus=usb_busses; bus; bus=bus->next )
00170         {
00171                 for( device=bus->devices; device; device=device->next )
00172                 {
00173                         printf(" Device found : Vendor=0x%x Product=0x%x\n", device->descriptor.idVendor, device->descriptor.idProduct );
00174                         if (device->descriptor.idVendor==idVendor && device->descriptor.idProduct==idProduct)
00175                         {
00176                                 printf(" Correct device found :-)\n");
00177                                 devHandle = usb_open( device );
00178                                 if (devHandle)
00179                                 {
00180                                         printf(" Device has been opened\n");
00181                                         return true;
00182                                 }
00183                                 else
00184                                 {
00185                                         fprintf(stderr, " Can't open device handle : %s\n", usb_strerror());
00186                                         return false;
00187                                 }
00188                         }
00189                 }
00190         }
00191         fprintf(stderr, "USB : Device %x, %x can't be found\n", idVendor, idProduct);
00192         return false;
00193 }
00194 
00195 bool EzUSB::downloadFirmware(const char *fn)
00196 {
00197         /* See http://www.anchorchips.com for the
00198          * EZ-USB Technical Reference Manual (EZUSB_TRM.pdf).
00199          */
00200         #define CPUCS 0x7f92
00201         #define USBSC 0x7fd6
00202 
00203         FILE *f=NULL;
00204         struct intels *hx, *d;
00205         char b[2];
00206         int count;
00207 
00208         if (!devHandle)
00209                 return false;
00210 
00211 //      usb_set_configuration(devHandle, 1);
00212 
00213         // Claim the interface
00214         if (usb_claim_interface(devHandle, 0)<0)
00215         {
00216                 fprintf(stderr, "USB : Can't claim interface : %s\n", usb_strerror());
00217                 return false;
00218         }
00219 
00220         // Set alternate interface
00221         if (usb_set_altinterface(devHandle,0) < 0 )
00222         {
00223                 fprintf(stderr, "USB : Can't set alternate interface : %s\n", usb_strerror());
00224                 return false;
00225         }
00226 
00227         // Open hex file
00228         const char *firmware = fn;
00229         if (filename && filename[0] != 0) // if the option -f <file> was provided
00230                 firmware = filename;    // use it.
00231         if (!(f=fileManagerPtr->openFP(firmware, "r")))
00232         {
00233                 fprintf(stderr, "USB : Can't open HEX file '%s' : %s\n", firmware, strerror(errno));
00234                 return false;
00235         }
00236 
00237         // Read hex file
00238         hx = NULL;
00239         if (!read_head(f, &hx))
00240         {
00241                 fprintf(stderr, "USB : Can't read HEX file\n");
00242                 fclose(f);
00243                 return false;
00244         }
00245         fclose(f);
00246 
00247         // Sent reset
00248         b[0] = 1;
00249         if (shunt(devHandle, CPUCS, (void *) b, 1)<0)
00250         {
00251                 fprintf(stderr, "USB : Could not send command to bring device in reset: %s\n", usb_strerror());
00252                 return false;
00253         }
00254         else
00255         {
00256                 printf("USB : Command to bring 8051 to reset sent.\n");
00257         }
00258 
00259         // Send data
00260         usleep(250000);
00261         printf("USB : Downloading ");
00262         count=0;
00263         for( d = hx; d; d = d->nxt)
00264         {
00265 #if 0
00266                 if ((d->len == 1) && (plen == 64) && (d->nxt == NULL))
00267                         fprintf(stderr,"Warning - Some chips cannot cope with 64*n+1 downloads\n"
00268                                         "See the erratum on the anchorchip.com site\n");
00269 #endif
00270                 if (shunt(devHandle, d->addr, (void *) (d->data), d->len)<0)
00271                 {
00272                         fprintf(stderr, "USB : Download failed : %s\n", usb_strerror());
00273                         return false;
00274                 }
00275 
00276                 printf(".");
00277                 fflush(stdout);
00278                 count++;
00279         }
00280 
00281         printf("\nUSB : All %d packets downloaded.\n", count);
00282         usleep(250000);
00283 
00284         b[0] = 0;
00285         if (shunt(devHandle, CPUCS, (void *) b, 1)<0)
00286         {
00287                 fprintf(stderr, "USB : Warning: Could not send command to get the device out of reset: %s\n", usb_strerror());
00288                 return false;
00289         }
00290         else
00291                 printf("USB : Command to bring 8051 out of reset sent.\n");
00292 
00293         usleep(100000);
00294 
00295         //usb_reset(devHandle);
00296         //findDevice();
00297 
00298         return true;
00299 }
00300 
00301 
00302 
00303 /* This whole reading routine sucks. you could do it in
00304  * about 12 lines with scanf(). But this is the result
00305  * from testing it on too many hex files which went through
00306  * mac/pc/unic/mail conversion loops.
00307  *
00308  * Conceptually the format is simple, just a hex
00309  * string prefixed by a colon and terminated by your
00310  * local flavour of a line break.
00311  *
00312  * ':' <len> <addr> <type> <len-data> <crc> '\r'
00313  * Where len, type and crc are two char hex, addr
00314  * is a 4 char hex value and len data is 2*len
00315  * hex chars.
00316  */
00317 
00318 int EzUSB::read_head(FILE * fh, struct intels * * doutp )
00319 {
00320         unsigned char crc;
00321         unsigned char buff[256*2 + 9 + 2 + 1];  /* read buffer */
00322         unsigned char tmp[5];           /* temp buf for conversions */
00323         unsigned char data[256];
00324         char *last;                     /* last character processed */
00325         int len, type, c, i;
00326         int line = 1;                   /* current line number */
00327         int comment = 0;                /* are we in a comment? */
00328         int addr; // quat_t :-)
00329 
00330 #define WHITESPACE      " \t_-\a"
00331 #define LFCR            "\r\n"
00332 #define COMMENT         "#;/*"
00333 
00334         /* macro for error printing */
00335 #define BAIL(x) \
00336         do { \
00337                 fprintf(stderr, "USB : %s at line %d\n", x, line); \
00338                 return 0; \
00339         } while(0)
00340 
00341         /* XXX silly way of doing it. Should add a cyclic
00342          * buffer of course. And you could use fscanf if
00343          * you are not worried about broken lines. But
00344          * unfortunately we are.
00345          */
00346         while(!feof(fh))
00347         {
00348 
00349                 /*
00350                  * read in the first 9 bytes:
00351                  * : <len> <addr> <type>  -> 1+2+4+2 = 9
00352                  */
00353 
00354                 for(i = 0; i < 9 && (c = fgetc(fh)) != EOF; /* noop */) {
00355                         if (index(LFCR, c)) {
00356                                 line++;
00357                                 comment = 0;
00358                                 continue;
00359                         } else if (index(WHITESPACE, c)) {
00360                                 continue;
00361                         } else if (index(COMMENT, c)) {
00362                                 comment = 1;
00363                         }
00364 
00365                         if (comment)
00366                                 continue;
00367 
00368                         buff[i] = c;
00369                         i++;
00370                 }
00371 
00372                 if (ferror(fh)) {
00373                         BAIL(strerror(errno));
00374                 } else if (feof(fh)) {
00375                         if (i)
00376                                 BAIL("HDR Truncated");
00377                         else
00378                                 BAIL("EOF before a type 1 line");
00379                 }
00380 
00381                 /* the colon at the begginning of the line */
00382                 if (buff[0] != ':')
00383                         BAIL("Colon expected");
00384 
00385                 /* the len field */
00386                 if (!isxdigit(buff[1]) || !isxdigit(buff[2]))
00387                         BAIL("Len malformed");
00388 
00389                 memcpy(tmp, buff+1, 2);
00390                 tmp[2]='\0';
00391                 len = strtol((const char *)tmp, &last, 16);
00392 
00393                 if (last[0] != '\0')            /* up to end of string? */
00394                         BAIL("Could not convert len");
00395                 if (len < 0 || len > 255)
00396                         BAIL("Bad len (>255)");
00397 
00398                 /* the addr field */
00399                 if (!isxdigit(buff[3]) || !isxdigit(buff[4]) ||
00400                     !isxdigit(buff[5]) || !isxdigit(buff[6]) )
00401                         BAIL("Addr malformed");
00402 
00403                 memcpy(tmp, buff+3, 4);
00404                 tmp[4]='\0';
00405                 addr = strtol((const char *)tmp, &last, 16);
00406                 if (last[0])                    /* up to end of string? */
00407                         BAIL("Could not convert addr");
00408 
00409                 /* the type field */
00410                 if (!isxdigit(buff[7]) || !isxdigit(buff[8]))
00411                         BAIL("Type malformed");
00412 
00413                 memcpy(tmp, buff+7, 2);
00414                 tmp[2]='\0';
00415                 type = strtol((const char *)tmp, &last, 16);
00416                 if (last[0] != '\0')            /* up to end of string? */
00417                         BAIL("Could not convert type");
00418                 if (type < 0 || type > 1)
00419                         BAIL("Unkown type (not one of 00, 01)");
00420 
00421                 /* read 2 * len pairs and a CRC.. */
00422                 for(i = 0; i < 2*(len)+2 && (c = fgetc(fh)) != EOF;) {
00423                         if (index(LFCR, c)) {
00424                                 line++;
00425                                 continue;
00426                         } else if (index(WHITESPACE, c)) {
00427                                 continue;
00428                         }
00429 
00430                         if (!isxdigit(c))
00431                                 BAIL("Malformed hex data");
00432 
00433                         buff[9+i] = c;
00434                         i++;
00435                 }
00436 
00437                 if (ferror(fh)) {
00438                         BAIL(strerror(errno));
00439                 } else if (i != 2*(len)+2) {
00440                         BAIL("data or CRC block Truncated");
00441                 }
00442 
00443                 for(i = 0; i < len+1+4; i++) {
00444                         memcpy(tmp, buff+1+i*2, 2);
00445                         tmp[2]='\0';
00446                         data[i] = strtol((const char *)tmp, &last, 16);
00447                         if (last[0] != '\0')    /* up to end of string? */
00448                                 BAIL("Could not convert data or crc pair");
00449                 }
00450 
00451                 for(crc = 0, i = 0; i < 4+len;i++)
00452                         crc += data[i];
00453 
00454                 crc = ~crc + 1;
00455                 if (crc != data[len+4])
00456                         BAIL("Checksum mismatch");
00457 
00458                 if (len && type == 0) {
00459                         *doutp = (struct intels *)malloc(sizeof(intels));
00460                         (*doutp)->addr = addr;
00461                         (*doutp)->len = len;
00462                         (*doutp)->data = (unsigned char *)malloc(len);
00463                         memcpy((*doutp)->data, data+4, len);
00464                         doutp = &( (*doutp)->nxt );
00465                 } else if (type == 1) {
00466                         break;
00467                 } else {
00468                         BAIL("Unkown intel type");
00469                 }
00470         }
00471 
00472         return 1;
00473 }
00474 
00475 int EzUSB::shunt(usb_dev_handle *pdev, int at, void *d, int len)
00476 {
00477         int err;
00478         err = usb_control_msg( pdev, 0x40,0xA0, at, 0, (char*)d, len, 1000 );
00479         return err;
00480 }

Generated on Fri May 16 13:01:45 2003 for Jelie by doxygen1.2.15