info commands
[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
26 #define CTL_DATA_BUS    0x55    /* refers to data bus controller */
27 #define CTL_ADDR_BUS    0xAA    /* .. address bus .. */
28
29 typedef struct {
30         u8 magic[4];
31         u8 reserved[11];
32         u8 magic2;
33         u8 mx_cmd;
34         union {
35                 struct {
36                         u8 which_device;
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];
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);
94
95         return ret;
96 }
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);
148                 fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
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
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
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;
199         int ret;
200
201         usb_init();
202
203         device = get_device();
204         if (device == NULL)
205                 return 1;
206
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;
216
217
218 end:
219         release_device(device);
220
221         return ret;
222 }
223