Merge latest bugfixes
[SCSI2SD-V6.git] / software / bootloaderhost / main.c
1 //      Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
2 //
3 //      This file is part of SCSI2SD.
4 //
5 //      SCSI2SD is free software: you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation, either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      SCSI2SD is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23
24
25 #include "hidapi.h"
26 #include "cybtldr_api.h"
27 #include "cybtldr_api2.h"
28
29 hid_device *handle = NULL;
30
31 static int OpenConnection(void)
32 {
33         return 0;
34 }
35
36 static int CloseConnection(void)
37 {
38         return 0;
39 }
40
41 static int ReadData(unsigned char* data, int count)
42 {
43         unsigned char buf[65];
44         buf[0] = 0; // Report ID
45
46         int result = hid_read(handle, buf, count);
47
48         if (result < 0)
49         {
50                 fprintf(stderr, "USB HID Read Failure: %ls\n", hid_error(handle));
51         }
52
53         memcpy(data, buf, count);
54
55         return (result >= 0) ? 0 : -1;
56 }
57
58 static int WriteData(unsigned char* data, int count)
59 {
60         unsigned char buf[65];
61         buf[0] = 0; // report ID
62         int i;
63         for (i = 0; i < count; ++i)
64         {
65                 buf[i+1] = data[i];
66         }
67         int result = hid_write(handle, buf, count + 1);
68
69         if (result < 0)
70         {
71                 fprintf(stderr, "USB HID Write Failure: %ls\n", hid_error(handle));
72         }
73
74         return (result >= 0) ? 0 : -1;
75 }
76
77
78 static void ProgressUpdate(unsigned char arrayId, unsigned short rowNum)
79 {
80         printf("Programmed flash array %d, row %d\n", arrayId, rowNum);
81 }
82
83 static void usage()
84 {
85         printf("Usage: bootloaderhost [-v UsbVendorId] [-p UsbProductId] [-f] /path/to/firmware.cyacd\n");
86         printf("\t-f\tForce, even if the firmware doesn't match the target board.\n");
87         printf("\n\n");
88 }
89
90 int main(int argc, char* argv[])
91 {
92         CyBtldr_CommunicationsData cyComms =
93         {
94                 &OpenConnection,
95                 &CloseConnection,
96                 &ReadData,
97                 &WriteData,
98                 64
99         };
100
101         printf("PSoC 3/5LP USB HID Bootloader Host\n");
102         printf("Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\n\n");
103
104         uint16_t vendorId = 0x04B4; // Cypress
105         uint16_t productId = 0xB71D; // Default PSoC3/5LP Bootloader
106         int force = 0;
107
108         opterr = 0;
109         int c;
110         while ((c = getopt(argc, argv, "v:p:f")) != -1)
111         {
112                 switch (c)
113                 {
114                 case 'v':
115                         sscanf(optarg, "%hx", &vendorId);
116                         break;
117                 case 'p':
118                         sscanf(optarg, "%hx", &productId);
119                         break;
120                 case 'f':
121                         force = 1;
122                         break;
123                 case '?':
124                         usage();
125                         exit(1);
126                 }
127         }
128
129         const char* filename;
130         if (optind < argc)
131         {
132                 filename = argv[optind];
133         }
134         else
135         {
136                 usage();
137                 exit(1);
138         }
139
140         printf(
141                 "USB device parameters\n\tVendor ID:\t0x%04X\n\tProduct ID:\t0x%04X\n",
142                 vendorId,
143                 productId);
144
145         // Enumerate and print the HID devices on the system
146         struct hid_device_info *dev = hid_enumerate(vendorId, productId);
147
148         if (!dev)
149         {
150                 printf("Waiting for device connection\n");
151                 printf("Connect USB cable to the bus-powered device now, or otherwise reset the device.\n");
152         }
153
154         while (!dev)
155         {
156                 dev = hid_enumerate(vendorId, productId);
157                 usleep(10000); // 10ms
158         }
159
160         printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls",
161                 dev->vendor_id, dev->product_id, dev->path, dev->serial_number);
162         printf("\n");
163         printf("  Manufacturer: %ls\n", dev->manufacturer_string);
164         printf("  Product:      %ls\n", dev->product_string);
165
166         int fileMismatch = 0;
167         const char* expectedName = NULL;
168         switch (dev->release_number)
169         {
170         case 0x3001:
171                 printf("  Release:      3.5\" SCSI2SD\n");
172                 expectedName = "SCSI2SD.cyacd";
173                 if (!strstr(filename, expectedName))
174                 {
175                         fileMismatch = 1;
176                 }
177                 break;
178         case 0x3002:
179                 printf("  Release:      2.5\" SCSI2SD for Apple Powerbook\n");
180                 expectedName = "pbook.cyacd";
181                 if (!strstr(filename, expectedName))
182                 {
183                         fileMismatch = 1;
184                 }
185                 break;
186         default:
187                 printf("  Release:      Unknown hardware\n");
188                 expectedName = "unknown";
189                 fileMismatch = 1;
190         }
191         printf("\n");
192
193         if (fileMismatch && !force)
194         {
195                 fprintf(stderr, "ERROR: Unexpected firmware file. Expected: \"%s\"\n"
196                         "Using firmware design for a different board may destroy your "
197                         "hardware.\n"
198                         "If you still wish to proceed, try again with the \"-f\" flag.\n",
199                         expectedName);
200                 exit(1);
201         }
202         //hid_free_enumeration(devs);
203
204         // Open the device using the VID, PID,
205         // and optionally the Serial number.
206         handle = hid_open(vendorId, productId, NULL);
207         if (!handle)
208         {
209                 fprintf(
210                         stderr,
211                         "Could not open device %s. Check permissions.\n", dev->path
212                         );
213                 exit(1);
214         }
215
216
217         printf("Starting firmware upload: %s\n", filename);
218         int result = CyBtldr_Program(
219                 filename,
220                 &cyComms,
221                 &ProgressUpdate);
222         if (result == 0)
223         {
224                 printf("Firmware update complete\n");
225         }
226         else
227         {
228                 printf("Firmware update failed\n");
229         }
230
231         return 0;
232 }
233