1 /*********************************************************************************************
2
3 Copyright header?
4
5 *********************************************************************************************/
6
7 #ifdef HAVE_CONFIG_H
8 # include "config.h"
9 #endif
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 //#include <usb.h>
15
16 #include "KWIQGuider.h"
17 #include "KWIQGuider_priv.h"
18 #include "KWIQGuider_firmware.h"
19
20 #define CPUCS_ADDRESS 0xe600
21
22 /* USB commands to control device */
23 enum USB_REQUEST {
24 USB_RQ_LOAD_FIRMWARE = 0xa0,
25 USB_RQ_WRITE_SMALL_EEPROM = 0xa2
26 };
27
28 using namespace KWIQ;
29
30 /* Bootloader data */
31 static unsigned char bootloader[] = { SSAG_BOOTLOADER };
32 /* Firmware data */
33 static unsigned char firmware[] = { SSAG_FIRMWARE };
34 /* EEPROM data (shouldn't be needed) */
35 // static unsigned char eeprom[] = { SSAG_EEPROM };
36
Connect()37 bool Loader::Connect()
38 {
39 if (!usb_open_device(&this->handle, SSAG_LOADER_VENDOR_ID, SSAG_LOADER_PRODUCT_ID, NULL)) {
40 return false;
41 }
42 return true;
43 }
44
Disconnect()45 void Loader::Disconnect()
46 {
47 if (this->handle)
48 libusb_close(this->handle);
49 this->handle = NULL;
50 }
51
EnterResetMode()52 void Loader::EnterResetMode()
53 {
54 char data = 0x01;
55 //usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, 0x7f92, 0, &data, 1, 5000);
56 int r = libusb_control_transfer(
57 this->handle,
58 0x40 & 0xff,
59 USB_RQ_LOAD_FIRMWARE & 0xff,
60 0x7f92 & 0xffff,
61 0 & 0xffff,
62 (unsigned char*)&data,
63 1,
64 5000);
65
66 if (r < 0)
67 {
68 DBG("Loader::EnterResetMode: error sending command (1)");
69 }
70
71
72 //usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, CPUCS_ADDRESS, 0, &data, 1, 5000);
73
74 r = libusb_control_transfer(
75 this->handle,
76 0x40 & 0xff,
77 USB_RQ_LOAD_FIRMWARE & 0xff,
78 CPUCS_ADDRESS & 0xffff,
79 0 & 0xffff,
80 (unsigned char*)&data,
81 1,
82 5000);
83
84 if (r < 0)
85 {
86 DBG("Loader::EnterResetMode: error sending command (2)");
87 }
88
89 }
90
ExitResetMode()91 void Loader::ExitResetMode()
92 {
93 char data = 0x00;
94 //usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, 0x7f92, 0, &data, 1, 5000);
95 int r = libusb_control_transfer(
96 this->handle,
97 0x40 & 0xff,
98 USB_RQ_LOAD_FIRMWARE & 0xff,
99 0x7f92 & 0xffff,
100 0 & 0xffff,
101 (unsigned char*)&data,
102 1,
103 5000);
104
105 if (r < 0)
106 {
107 DBG("Loader::ExitResetMode: error sending command (1)");
108 }
109
110
111 //usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, CPUCS_ADDRESS, 0, &data, 1, 5000);
112
113 r = libusb_control_transfer(
114 this->handle,
115 0x40 & 0xff,
116 USB_RQ_LOAD_FIRMWARE & 0xff,
117 CPUCS_ADDRESS & 0xffff,
118 0 & 0xffff,
119 (unsigned char*)&data,
120 1,
121 5000);
122
123 if (r < 0)
124 {
125 DBG("Loader::ExitResetMode: error sending command (2)");
126 }
127 }
128
Upload(unsigned char * data)129 bool Loader::Upload(unsigned char *data)
130 {
131 for (;;) {
132 unsigned char byte_count = *data;
133 if (byte_count == 0)
134 break;
135 unsigned short address = *(unsigned int *)(data+1);
136 int received = 0;
137
138 //usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, address, 0, (char *)(data+3), byte_count, 5000))
139 received = libusb_control_transfer(
140 this->handle,
141 0x40 & 0xff,
142 USB_RQ_LOAD_FIRMWARE & 0xff,
143 address & 0xffff,
144 0 & 0xffff,
145 (unsigned char*)(data+3),
146 byte_count,
147 5000);
148
149
150 //if ((received = usb_control_msg(this->handle, 0x40, USB_RQ_LOAD_FIRMWARE, address, 0, (char *)(data+3), byte_count, 5000)) != byte_count) {
151
152 if (received != byte_count) {
153
154 DBG("ERROR: Tried to send %d bytes of data but device reported back with %d\n", byte_count, received);
155 return false;
156 }
157 data += byte_count + 3;
158 }
159 return true;
160 }
161
LoadFirmware()162 bool Loader::LoadFirmware()
163 {
164 /* Load bootloader */
165 this->EnterResetMode();
166 this->EnterResetMode();
167 DBG("Loading bootloader...");
168 if (!this->Upload(bootloader))
169 return false;
170 DBG("done\n");
171 this->ExitResetMode(); /* Transfer execution to the reset vector */
172
173 sleep(1); /* Wait for renumeration */
174
175 /* Load firmware */
176 this->EnterResetMode();
177 DBG("Loading firmware...");
178 if (!this->Upload(firmware))
179 return false;
180 DBG("done\n");
181 this->EnterResetMode(); /* Make sure the CPU is in reset */
182 this->ExitResetMode(); /* Transfer execution to the reset vector */
183
184 return true;
185 }
186
187 /*** FOR NOW, AT LEAST, DON'T DO THIS, ESPECIALLY ACCIDENTALLY???
188 bool Loader::LoadEEPROM()
189 {
190 size_t length = *eeprom;
191 char *data = (char *)(eeprom+3);
192 usb_control_msg(this->handle, 0x40, USB_RQ_WRITE_SMALL_EEPROM, 0x00, 0xBEEF, data, length, 5000);
193
194 return true;
195 }
196 ***/
197