filename getter
[megadrive.git] / mx / linux / main.c
1 #include <stdio.h>
2 #include <string.h>
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
24 #define CMD_ATM_READY           0x22
25 #define CMD_SEC_GET_NAME        'G'     /* read filename */
26
27 /* bus controllers */
28 #define CTL_DATA_BUS    0x55
29 #define CTL_ADDR_BUS    0xAA
30
31 #define FILENAME_ROM0   0
32 #define FILENAME_ROM1   1
33 #define FILENAME_RAM    2
34
35 typedef struct {
36         u8 magic[4];
37         u8 reserved[11];
38         u8 magic2;
39         u8 mx_cmd;
40         union {
41                 struct {
42                         u8 which_device;
43                 } dev_info;
44                 struct {
45                         u8 addrb2;      /* most significant */
46                         u8 addrb1;
47                         u8 addrb0;
48                         u8 num_pages;
49                 } rom_rw;
50                 struct {
51                         u8 which;
52                 } filename;
53                 struct {
54                         u8 times_cmd;
55                         u8 action;
56                         u8 cntb3;
57                         u8 cntb2;
58                         u8 cntb1;
59                         u8 cntb0;
60                 } times_write;
61         };
62         u8 pad[8];
63 } dev_cmd_t;
64
65 typedef struct {
66         u8 firmware_ver[4];
67         u8 bootloader_ver[4];
68         char names[56];
69 } dev_info_t;
70
71 static void prepare_cmd(dev_cmd_t *dev_cmd, u8 cmd)
72 {
73         memset(dev_cmd, 0, sizeof(*dev_cmd));
74
75         memcpy(dev_cmd->magic, "USBC", 4);
76         dev_cmd->magic2 = 0x67; /* MySCSICommand, EXCOMMAND */
77         dev_cmd->mx_cmd = cmd;
78 }
79
80 static int write_cmd(struct usb_dev_handle *dev, dev_cmd_t *cmd)
81 {
82         int ret = usb_bulk_write(dev, 0x03, (char *)cmd, sizeof(*cmd), 2000);
83         if (ret < 0) {
84                 fprintf(stderr, "failed to write:\n");
85                 fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
86         } else if (ret != sizeof(*cmd))
87                 printf("write_cmd: wrote only %d of %d bytes\n", ret, sizeof(*cmd));
88         
89         return ret;
90 }
91
92 static int read_response(struct usb_dev_handle *dev, void *buff, int size)
93 {
94         int ret = usb_bulk_read(dev, 0x82, buff, size, 2000);
95         if (ret < 0) {
96                 fprintf(stderr, "failed to read:\n");
97                 fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
98         } else if (ret != size)
99                 printf("read_response: read only %d of %d bytes\n", ret, size);
100
101         return ret;
102 }
103
104 static int read_info(struct usb_dev_handle *device, u8 ctl_id)
105 {
106         dev_cmd_t cmd;
107         dev_info_t info;
108         int ret;
109
110         prepare_cmd(&cmd, CMD_ATM_READY);
111         cmd.dev_info.which_device = ctl_id;
112         memset(&info, 0, sizeof(info));
113
114         ret = write_cmd(device, &cmd);
115         if (ret < 0)
116                 return ret;
117
118         ret = read_response(device, &info, sizeof(info));
119         if (ret < 0)
120                 return ret;
121         
122         printf(" firmware version:   %X.%X.%X%c\n", info.firmware_ver[0],
123                 info.firmware_ver[1], info.firmware_ver[2], info.firmware_ver[3]);
124         printf(" bootloader version: %X.%X.%X%c\n", info.bootloader_ver[0],
125                 info.bootloader_ver[1], info.bootloader_ver[2], info.bootloader_ver[3]);
126         info.names[sizeof(info.names) - 1] = 0;
127         printf(" device name:        %s\n", info.names);
128
129         return 0;
130 }
131
132 static int get_filename(struct usb_dev_handle *dev, char *dst, int len, u8 which)
133 {
134         char buff[65];
135         dev_cmd_t cmd;
136         int ret;
137
138         prepare_cmd(&cmd, CMD_SEC_GET_NAME);
139         cmd.filename.which = which;
140         memset(buff, 0, sizeof(buff));
141
142         ret = write_cmd(dev, &cmd);
143         if (ret < 0)
144                 return ret;
145
146         ret = read_response(dev, buff, 64);
147         if (ret < 0)
148                 return ret;
149
150         strncpy(dst, buff, len);
151         dst[len - 1] = 0;
152
153         return 0;
154 }
155
156 static usb_dev_handle *get_device(void)
157 {
158         struct usb_dev_handle *handle;
159         struct usb_device *dev;
160         struct usb_bus *bus;
161         int i, ret;
162
163         ret = usb_find_busses();
164         if (ret <= 0) {
165                 fprintf(stderr, "Can't find USB busses\n");
166                 return NULL;
167         }
168
169         ret = usb_find_devices();
170         if (ret <= 0) {
171                 fprintf(stderr, "Can't find USB devices\n");
172                 return NULL;
173         }
174
175         bus = usb_get_busses();
176         for (; bus; bus = bus->next)
177         {
178                 for (dev = bus->devices; dev; dev = dev->next)
179                 {
180                         for (i = 0; i < array_size(g_devices); i++)
181                         {
182                                 if (dev->descriptor.idVendor == g_devices[i].vendor &&
183                                                 dev->descriptor.idProduct == g_devices[i].product)
184                                         goto found;
185                         }
186                 }
187         }
188
189         fprintf(stderr, "device not found.\n");
190         return NULL;
191
192 found:
193         printf("found %s.\n", g_devices[i].name);
194
195         handle = usb_open(dev);
196         if (handle == NULL) {
197                 fprintf(stderr, "failed to open device:\n");
198                 fprintf(stderr, "%s\n", usb_strerror());
199                 return NULL;
200         }
201
202         ret = usb_set_configuration(handle, 1);
203         if (ret != 0) {
204                 fprintf(stderr, "couldn't set configuration for /*/bus/usb/%s/%s:\n",
205                         bus->dirname, dev->filename);
206                 fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
207                 return NULL;
208         }
209
210         ret = usb_claim_interface(handle, 0);
211         if (ret != 0) {
212                 fprintf(stderr, "couldn't claim /*/bus/usb/%s/%s:\n",
213                         bus->dirname, dev->filename);
214                 fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
215                 return NULL;
216         }
217
218         return handle;
219 }
220
221 static void release_device(struct usb_dev_handle *device)
222 {
223         usb_release_interface(device, 0);
224         usb_close(device);
225 }
226
227 int main(int argc, char *argv[])
228 {
229         struct usb_dev_handle *device;
230         char fname[65];
231         int ret;
232
233         usb_init();
234
235         device = get_device();
236         if (device == NULL)
237                 return 1;
238
239         printf("data bus controller:\n");
240         ret = read_info(device, CTL_DATA_BUS);
241         if (ret < 0)
242                 goto end;
243
244         printf("address bus controller:\n");
245         ret = read_info(device, CTL_ADDR_BUS);
246         if (ret < 0)
247                 goto end;
248
249         ret = get_filename(device, fname, sizeof(fname), FILENAME_ROM0);
250         if (ret < 0)
251                 goto end;
252         printf("ROM filename:  %s\n", fname);
253
254         ret = get_filename(device, fname, sizeof(fname), FILENAME_RAM);
255         if (ret < 0)
256                 goto end;
257         printf("SRAM filename: %s\n", fname);
258
259
260
261 end:
262         release_device(device);
263
264         return ret;
265 }
266