Merge Powerbook pcb updates
[SCSI2SD.git] / software / bootloaderhost / main.c
CommitLineData
2db48d92
MM
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>
c693c7fa
MM
19#include <stdio.h>
20#include <stdlib.h>
2db48d92
MM
21#include <string.h>
22#include <unistd.h>
23
c693c7fa
MM
24
25#include "hidapi.h"
26#include "cybtldr_api.h"
27#include "cybtldr_api2.h"
28
29hid_device *handle = NULL;
30
31static int OpenConnection(void)
32{
33 return 0;
34}
35
36static int CloseConnection(void)
37{
38 return 0;
39}
40
41static int ReadData(unsigned char* data, int count)
42{
2db48d92
MM
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;
c693c7fa
MM
56}
57
58static 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 }
2db48d92
MM
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
c693c7fa
MM
74 return (result >= 0) ? 0 : -1;
75}
76
77
78static void ProgressUpdate(unsigned char arrayId, unsigned short rowNum)
79{
2db48d92 80 printf("Programmed flash array %d, row %d\n", arrayId, rowNum);
c693c7fa
MM
81}
82
2db48d92 83static void usage()
c693c7fa 84{
abe0a5f5
MM
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");
2db48d92
MM
87 printf("\n\n");
88}
c693c7fa 89
2db48d92
MM
90int main(int argc, char* argv[])
91{
c693c7fa
MM
92 CyBtldr_CommunicationsData cyComms =
93 {
94 &OpenConnection,
95 &CloseConnection,
96 &ReadData,
97 &WriteData,
98 64
99 };
100
2db48d92
MM
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
abe0a5f5 106 int force = 0;
2db48d92
MM
107
108 opterr = 0;
109 int c;
abe0a5f5 110 while ((c = getopt(argc, argv, "v:p:f")) != -1)
2db48d92
MM
111 {
112 switch (c)
113 {
114 case 'v':
32a39b08 115 sscanf(optarg, "%hx", &vendorId);
2db48d92
MM
116 break;
117 case 'p':
32a39b08 118 sscanf(optarg, "%hx", &productId);
2db48d92 119 break;
abe0a5f5
MM
120 case 'f':
121 force = 1;
122 break;
2db48d92
MM
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
c693c7fa 145 // Enumerate and print the HID devices on the system
2db48d92 146 struct hid_device_info *dev = hid_enumerate(vendorId, productId);
c693c7fa 147
2db48d92 148 if (!dev)
c693c7fa 149 {
2db48d92
MM
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);
c693c7fa
MM
157 usleep(10000); // 10ms
158 }
2db48d92 159
c693c7fa
MM
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);
abe0a5f5
MM
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 }
c693c7fa 191 printf("\n");
abe0a5f5
MM
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 }
c693c7fa
MM
202 //hid_free_enumeration(devs);
203
204 // Open the device using the VID, PID,
205 // and optionally the Serial number.
2db48d92
MM
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 }
c693c7fa
MM
215
216
2db48d92
MM
217 printf("Starting firmware upload: %s\n", filename);
218 int result = CyBtldr_Program(
219 filename,
c693c7fa
MM
220 &cyComms,
221 &ProgressUpdate);
2db48d92
MM
222 if (result == 0)
223 {
224 printf("Firmware update complete\n");
225 }
226 else
227 {
228 printf("Firmware update failed\n");
229 }
c693c7fa
MM
230
231 return 0;
232}
233