info commands
[megadrive.git] / mx / linux / main.c
CommitLineData
8c8e818c 1#include <stdio.h>
726b85c8 2#include <string.h>
8c8e818c 3#include <usb.h>
4
5
6typedef unsigned char u8;
7typedef unsigned short u16;
8typedef unsigned int u32;
9#define array_size(x) (sizeof(x) / sizeof(x[0]))
10
11static 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
29typedef 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
59typedef struct {
60 u8 firmware_ver[4];
61 u8 bootloader_ver[4];
62 char names[56];
63} dev_info_t;
64
65static 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
74static 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
86static 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
98static 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
134found:
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 163static 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 190static void release_device(struct usb_dev_handle *device)
191{
192 usb_release_interface(device, 0);
193 usb_close(device);
194}
195
196int 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 218end:
8c8e818c 219 release_device(device);
220
726b85c8 221 return ret;
8c8e818c 222}
223