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