8c8e818c |
1 | #include <stdio.h> |
726b85c8 |
2 | #include <string.h> |
8c8e818c |
3 | #include <usb.h> |
4 | |
5 | |
6 | typedef unsigned char u8; |
7 | typedef unsigned short u16; |
8 | typedef unsigned int u32; |
9 | #define array_size(x) (sizeof(x) / sizeof(x[0])) |
10 | |
11 | static const struct { |
12 | unsigned short vendor; |
13 | unsigned short product; |
14 | const char *name; |
15 | } g_devices[] = { |
16 | { 0x03eb, 0x202a, "16MX+U Game Device" }, |
17 | { 0x03eb, 0x202b, "32MX+U Game Device" }, |
18 | { 0x03eb, 0x202c, "16MX+US Game Device" }, |
19 | { 0x03eb, 0x202d, "32MX+UF Game Device" }, |
20 | }; |
21 | |
22 | /*****************************************************************************/ |
23 | |
726b85c8 |
24 | #define CMD_ATM_READY 0x22 |
25 | |
26 | #define CTL_DATA_BUS 0x55 /* refers to data bus controller */ |
27 | #define CTL_ADDR_BUS 0xAA /* .. address bus .. */ |
28 | |
29 | typedef struct { |
8c8e818c |
30 | u8 magic[4]; |
31 | u8 reserved[11]; |
32 | u8 magic2; |
33 | u8 mx_cmd; |
34 | union { |
35 | struct { |
36 | u8 which_device; |
8c8e818c |
37 | } dev_info; |
38 | struct { |
39 | u8 addrb2; /* most significant */ |
40 | u8 addrb1; |
41 | u8 addrb0; |
42 | u8 num_pages; |
43 | } rom_rw; |
44 | struct { |
45 | u8 position; |
46 | } filename; |
47 | struct { |
48 | u8 times_cmd; |
49 | u8 action; |
50 | u8 cntb3; |
51 | u8 cntb2; |
52 | u8 cntb1; |
53 | u8 cntb0; |
54 | } times_write; |
55 | }; |
56 | u8 pad[8]; |
726b85c8 |
57 | } dev_cmd_t; |
58 | |
59 | typedef struct { |
60 | u8 firmware_ver[4]; |
61 | u8 bootloader_ver[4]; |
62 | char names[56]; |
63 | } dev_info_t; |
64 | |
65 | static void prepare_cmd(dev_cmd_t *dev_cmd, u8 cmd) |
66 | { |
67 | memset(dev_cmd, 0, sizeof(*dev_cmd)); |
68 | |
69 | memcpy(dev_cmd->magic, "USBC", 4); |
70 | dev_cmd->magic2 = 0x67; /* "MySCSICommand" */ |
71 | dev_cmd->mx_cmd = cmd; |
72 | } |
73 | |
74 | static int write_cmd(struct usb_dev_handle *dev, dev_cmd_t *cmd) |
75 | { |
76 | int ret = usb_bulk_write(dev, 0x03, (char *)cmd, sizeof(*cmd), 2000); |
77 | if (ret < 0) { |
78 | fprintf(stderr, "failed to write:\n"); |
79 | fprintf(stderr, "%s (%d)\n", usb_strerror(), ret); |
80 | } else if (ret != sizeof(*cmd)) |
81 | printf("write_cmd: wrote only %d of %d bytes\n", ret, sizeof(*cmd)); |
82 | |
83 | return ret; |
84 | } |
85 | |
86 | static int read_response(struct usb_dev_handle *dev, void *buff, int size) |
87 | { |
88 | int ret = usb_bulk_read(dev, 0x82, buff, size, 2000); |
89 | if (ret < 0) { |
90 | fprintf(stderr, "failed to read:\n"); |
91 | fprintf(stderr, "%s (%d)\n", usb_strerror(), ret); |
92 | } else if (ret != size) |
93 | printf("read_response: read only %d of %d bytes\n", ret, size); |
8c8e818c |
94 | |
726b85c8 |
95 | return ret; |
96 | } |
8c8e818c |
97 | |
98 | static usb_dev_handle *get_device(void) |
99 | { |
100 | struct usb_dev_handle *handle; |
101 | struct usb_device *dev; |
102 | struct usb_bus *bus; |
103 | int i, ret; |
104 | |
105 | ret = usb_find_busses(); |
106 | if (ret <= 0) { |
107 | fprintf(stderr, "Can't find USB busses\n"); |
108 | return NULL; |
109 | } |
110 | |
111 | ret = usb_find_devices(); |
112 | if (ret <= 0) { |
113 | fprintf(stderr, "Can't find USB devices\n"); |
114 | return NULL; |
115 | } |
116 | |
117 | bus = usb_get_busses(); |
118 | for (; bus; bus = bus->next) |
119 | { |
120 | for (dev = bus->devices; dev; dev = dev->next) |
121 | { |
122 | for (i = 0; i < array_size(g_devices); i++) |
123 | { |
124 | if (dev->descriptor.idVendor == g_devices[i].vendor && |
125 | dev->descriptor.idProduct == g_devices[i].product) |
126 | goto found; |
127 | } |
128 | } |
129 | } |
130 | |
131 | fprintf(stderr, "device not found.\n"); |
132 | return NULL; |
133 | |
134 | found: |
135 | printf("found %s.\n", g_devices[i].name); |
136 | |
137 | handle = usb_open(dev); |
138 | if (handle == NULL) { |
139 | fprintf(stderr, "failed to open device:\n"); |
140 | fprintf(stderr, "%s\n", usb_strerror()); |
141 | return NULL; |
142 | } |
143 | |
144 | ret = usb_set_configuration(handle, 1); |
145 | if (ret != 0) { |
146 | fprintf(stderr, "couldn't set configuration for /*/bus/usb/%s/%s:\n", |
147 | bus->dirname, dev->filename); |
726b85c8 |
148 | fprintf(stderr, "%s (%d)\n", usb_strerror(), ret); |
8c8e818c |
149 | return NULL; |
150 | } |
151 | |
152 | ret = usb_claim_interface(handle, 0); |
153 | if (ret != 0) { |
154 | fprintf(stderr, "couldn't claim /*/bus/usb/%s/%s:\n", |
155 | bus->dirname, dev->filename); |
156 | fprintf(stderr, "%s (%d)\n", usb_strerror(), ret); |
157 | return NULL; |
158 | } |
159 | |
160 | return handle; |
161 | } |
162 | |
726b85c8 |
163 | static int read_info(struct usb_dev_handle *device, u8 ctl_id) |
164 | { |
165 | dev_cmd_t cmd; |
166 | dev_info_t info; |
167 | int ret; |
168 | |
169 | prepare_cmd(&cmd, CMD_ATM_READY); |
170 | cmd.dev_info.which_device = ctl_id; |
171 | |
172 | ret = write_cmd(device, &cmd); |
173 | if (ret < 0) |
174 | return ret; |
175 | |
176 | ret = read_response(device, &info, sizeof(info)); |
177 | if (ret < 0) |
178 | return ret; |
179 | |
180 | printf("firmware version: %X.%X.%X%c\n", info.firmware_ver[0], |
181 | info.firmware_ver[1], info.firmware_ver[2], info.firmware_ver[3]); |
182 | printf("bootloader version: %X.%X.%X%c\n", info.bootloader_ver[0], |
183 | info.bootloader_ver[1], info.bootloader_ver[2], info.bootloader_ver[3]); |
184 | info.names[sizeof(info.names) - 1] = 0; |
185 | printf("device name: %s\n", info.names); |
186 | |
187 | return 0; |
188 | } |
189 | |
8c8e818c |
190 | static void release_device(struct usb_dev_handle *device) |
191 | { |
192 | usb_release_interface(device, 0); |
193 | usb_close(device); |
194 | } |
195 | |
196 | int main(int argc, char *argv[]) |
197 | { |
198 | struct usb_dev_handle *device; |
726b85c8 |
199 | int ret; |
8c8e818c |
200 | |
201 | usb_init(); |
202 | |
203 | device = get_device(); |
204 | if (device == NULL) |
205 | return 1; |
206 | |
726b85c8 |
207 | printf("data bus controller:\n"); |
208 | ret = read_info(device, CTL_DATA_BUS); |
209 | if (ret < 0) |
210 | goto end; |
211 | |
212 | printf("address bus controller:\n"); |
213 | ret = read_info(device, CTL_ADDR_BUS); |
214 | if (ret < 0) |
215 | goto end; |
8c8e818c |
216 | |
217 | |
726b85c8 |
218 | end: |
8c8e818c |
219 | release_device(device); |
220 | |
726b85c8 |
221 | return ret; |
8c8e818c |
222 | } |
223 | |