Merged with trunk R1612.
[ardour.git] / libs / surfaces / frontier / tests / tranzport.c
1 /*
2  * tranzport 0.1 <tranzport.sf.net>
3  * oct 18, 2005
4  * arthur@artcmusic.com
5  */
6
7 #include <stdarg.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <usb.h>
12
13 #define VENDORID  0x165b
14 #define PRODUCTID 0x8101
15
16 #define READ_ENDPOINT  0x81
17 #define WRITE_ENDPOINT 0x02
18
19 enum {
20         LIGHT_RECORD = 0,
21         LIGHT_TRACKREC,
22         LIGHT_TRACKMUTE,
23         LIGHT_TRACKSOLO,
24         LIGHT_ANYSOLO,
25         LIGHT_LOOP,
26         LIGHT_PUNCH
27 };
28
29 #define BUTTONMASK_BATTERY     0x00004000
30 #define BUTTONMASK_BACKLIGHT   0x00008000
31 #define BUTTONMASK_TRACKLEFT   0x04000000
32 #define BUTTONMASK_TRACKRIGHT  0x40000000
33 #define BUTTONMASK_TRACKREC    0x00040000
34 #define BUTTONMASK_TRACKMUTE   0x00400000
35 #define BUTTONMASK_TRACKSOLO   0x00000400
36 #define BUTTONMASK_UNDO        0x80000000
37 #define BUTTONMASK_IN          0x02000000
38 #define BUTTONMASK_OUT         0x20000000
39 #define BUTTONMASK_PUNCH       0x00800000
40 #define BUTTONMASK_LOOP        0x00080000
41 #define BUTTONMASK_PREV        0x00020000
42 #define BUTTONMASK_ADD         0x00200000
43 #define BUTTONMASK_NEXT        0x00000200
44 #define BUTTONMASK_REWIND      0x01000000
45 #define BUTTONMASK_FASTFORWARD 0x10000000
46 #define BUTTONMASK_STOP        0x00010000
47 #define BUTTONMASK_PLAY        0x00100000
48 #define BUTTONMASK_RECORD      0x00000100
49 #define BUTTONMASK_SHIFT       0x08000000
50
51 #define STATUS_OFFLINE 0xff
52 #define STATUS_ONLINE  0x01
53
54 struct tranzport_s {
55         struct usb_device *dev;
56         usb_dev_handle *udev;
57 };
58
59 typedef struct tranzport_s tranzport_t;
60
61 void log_entry(FILE *fp, char *format, va_list ap)
62 {
63         vfprintf(fp, format, ap);
64         fputc('\n', fp);
65 }
66
67 void log_error(char *format, ...)
68 {
69         va_list ap;
70         va_start(ap, format);
71         log_entry(stderr, format, ap);
72         va_end(ap);
73 }
74
75 void vlog_error(char *format, va_list ap)
76 {
77         log_entry(stderr, format, ap);
78 }
79
80 void die(char *format, ...)
81 {
82         va_list ap;
83         va_start(ap, format);
84         vlog_error(format, ap);
85         va_end(ap);
86         exit(1);
87 }
88
89 tranzport_t *open_tranzport_core(struct usb_device *dev)
90 {
91         tranzport_t *z;
92         int val;
93
94         z = malloc(sizeof(tranzport_t));
95         if (!z)
96                 die("not enough memory");
97         memset(z, 0, sizeof(tranzport_t));
98
99         z->dev = dev;
100         z->udev = usb_open(z->dev);
101         if (!z->udev)
102                 die("unable to open tranzport");
103
104         val = usb_claim_interface(z->udev, 0);
105         if (val < 0)
106                 die("unable to claim tranzport");
107
108         return z;
109 }
110
111 tranzport_t *open_tranzport()
112 {
113         struct usb_bus *bus;
114         struct usb_device *dev;
115
116         usb_init();
117         usb_find_busses();
118         usb_find_devices();
119
120         for(bus=usb_busses; bus; bus=bus->next) {
121                 for(dev=bus->devices; dev; dev=dev->next) {
122                         if (dev->descriptor.idVendor != VENDORID)
123                                 continue;
124                         if (dev->descriptor.idProduct != PRODUCTID)
125                                 continue;
126
127                         return open_tranzport_core(dev);
128                 }
129         }
130
131         die("can't find tranzport");
132         return 0;
133 }
134
135 void close_tranzport(tranzport_t *z)
136 {
137         int val;
138
139         val = usb_release_interface(z->udev, 0);
140         if (val < 0)
141                 log_error("unable to release tranzport");
142
143         val = usb_close(z->udev);
144         if (val < 0)
145                 log_error("unable to close tranzport");
146
147         free(z);
148 }
149
150 int tranzport_write_core(tranzport_t *z, uint8_t *cmd, int timeout)
151 {
152         int val;
153         val = usb_interrupt_write(z->udev, WRITE_ENDPOINT, cmd, 8, timeout);
154         if (val < 0)
155                 return val;
156         if (val != 8)
157                 return -1;
158         return 0;
159 }
160
161 int tranzport_lcdwrite(tranzport_t *z, uint8_t cell, char *text, int timeout)
162 {
163         uint8_t cmd[8];
164
165         if (cell > 9) {
166                 return -1;
167         }
168
169         cmd[0] = 0x00;
170         cmd[1] = 0x01;
171         cmd[2] = cell;
172         cmd[3] = text[0];
173         cmd[4] = text[1];
174         cmd[5] = text[2];
175         cmd[6] = text[3];
176         cmd[7] = 0x00;
177
178         return tranzport_write_core(z, cmd, timeout);
179 }
180
181 int tranzport_lighton(tranzport_t *z, uint8_t light, int timeout)
182 {
183         uint8_t cmd[8];
184
185         cmd[0] = 0x00;
186         cmd[1] = 0x00;
187         cmd[2] = light;
188         cmd[3] = 0x01;
189         cmd[4] = 0x00;
190         cmd[5] = 0x00;
191         cmd[6] = 0x00;
192         cmd[7] = 0x00;
193
194         return tranzport_write_core(z, cmd, timeout);
195 }
196
197 int tranzport_lightoff(tranzport_t *z, uint8_t light, int timeout)
198 {
199         uint8_t cmd[8];
200
201         cmd[0] = 0x00;
202         cmd[1] = 0x00;
203         cmd[2] = light;
204         cmd[3] = 0x00;
205         cmd[4] = 0x00;
206         cmd[5] = 0x00;
207         cmd[6] = 0x00;
208         cmd[7] = 0x00;
209
210         return tranzport_write_core(z, cmd, timeout);
211 }
212
213 int tranzport_read(tranzport_t *z, uint8_t *status, uint32_t *buttons, uint8_t *datawheel, int timeout)
214 {
215         uint8_t buf[8];
216         int val;
217
218         memset(buf, 0, 8);
219         val = usb_interrupt_read(z->udev, READ_ENDPOINT, buf, 8, timeout);
220         if (val < 0)
221                 return val;
222         if (val != 8)
223                 return -1;
224
225         /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
226
227         *status = buf[1];
228
229         *buttons = 0;
230         *buttons |= buf[2] << 24;
231         *buttons |= buf[3] << 16;
232         *buttons |= buf[4] << 8;
233         *buttons |= buf[5];
234
235         *datawheel = buf[6];
236
237         return 0;
238 }
239
240 void lights_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, uint8_t light)
241 {
242         if (buttons & buttonmask) {
243                 if (buttons & BUTTONMASK_SHIFT) {
244                         tranzport_lightoff(z, light, 1000);
245                 } else {
246                         tranzport_lighton(z, light, 1000);
247                 }
248         }
249 }
250
251 void do_lights(tranzport_t *z, uint32_t buttons)
252 {
253         lights_core(z, buttons, BUTTONMASK_RECORD, LIGHT_RECORD);
254         lights_core(z, buttons, BUTTONMASK_TRACKREC, LIGHT_TRACKREC);
255         lights_core(z, buttons, BUTTONMASK_TRACKMUTE, LIGHT_TRACKMUTE);
256         lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_TRACKSOLO);
257         lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_ANYSOLO);
258         lights_core(z, buttons, BUTTONMASK_PUNCH, LIGHT_PUNCH);
259         lights_core(z, buttons, BUTTONMASK_LOOP, LIGHT_LOOP);
260 }
261
262 void buttons_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, char *str)
263 {
264         if (buttons & buttonmask)
265                 printf(" %s", str);
266 }
267
268 void do_buttons(tranzport_t *z, uint32_t buttons, uint8_t datawheel)
269 {
270         printf("buttons:");
271         buttons_core(z, buttons, BUTTONMASK_BATTERY, "battery");
272         buttons_core(z, buttons, BUTTONMASK_BACKLIGHT, "backlight");
273         buttons_core(z, buttons, BUTTONMASK_TRACKLEFT, "trackleft");
274         buttons_core(z, buttons, BUTTONMASK_TRACKRIGHT, "trackright");
275         buttons_core(z, buttons, BUTTONMASK_TRACKREC, "trackrec");
276         buttons_core(z, buttons, BUTTONMASK_TRACKMUTE, "trackmute");
277         buttons_core(z, buttons, BUTTONMASK_TRACKSOLO, "tracksolo");
278         buttons_core(z, buttons, BUTTONMASK_UNDO, "undo");
279         buttons_core(z, buttons, BUTTONMASK_IN, "in");
280         buttons_core(z, buttons, BUTTONMASK_OUT, "out");
281         buttons_core(z, buttons, BUTTONMASK_PUNCH, "punch");
282         buttons_core(z, buttons, BUTTONMASK_LOOP, "loop");
283         buttons_core(z, buttons, BUTTONMASK_PREV, "prev");
284         buttons_core(z, buttons, BUTTONMASK_ADD, "add");
285         buttons_core(z, buttons, BUTTONMASK_NEXT, "next");
286         buttons_core(z, buttons, BUTTONMASK_REWIND, "rewind");
287         buttons_core(z, buttons, BUTTONMASK_FASTFORWARD, "fastforward");
288         buttons_core(z, buttons, BUTTONMASK_STOP, "stop");
289         buttons_core(z, buttons, BUTTONMASK_PLAY, "play");
290         buttons_core(z, buttons, BUTTONMASK_RECORD, "record");
291         buttons_core(z, buttons, BUTTONMASK_SHIFT, "shift");
292         if (datawheel)
293                 printf(" datawheel=%02x", datawheel);
294         printf("\n");
295 }
296
297 void do_lcd(tranzport_t *z)
298 {
299         tranzport_lcdwrite(z, 0, "    ", 1000);
300         tranzport_lcdwrite(z, 1, "DISL", 1000);
301         tranzport_lcdwrite(z, 2, "EXIA", 1000);
302         tranzport_lcdwrite(z, 3, " FOR", 1000);
303         tranzport_lcdwrite(z, 4, "    ", 1000);
304
305         tranzport_lcdwrite(z, 5, "    ", 1000);
306         tranzport_lcdwrite(z, 6, " CUR", 1000);
307         tranzport_lcdwrite(z, 7, "E FO", 1000);
308         tranzport_lcdwrite(z, 8, "UND ", 1000);
309         tranzport_lcdwrite(z, 9, "    ", 1000);
310 }
311
312 int main()
313 {
314         tranzport_t *z;
315         uint8_t status;
316         uint32_t buttons;
317         uint8_t datawheel;
318         int val;
319
320         z = open_tranzport();
321
322         do_lcd(z);
323
324         for(;;) {
325                 val = tranzport_read(z, &status, &buttons, &datawheel, 60000);
326                 if (val < 0)
327                         continue;
328
329                 if (status == STATUS_OFFLINE) {
330                         printf("offline\n");
331                         continue;
332                 }
333
334                 if (status == STATUS_ONLINE) {
335                         printf("online\n");
336                         do_lcd(z);
337                 }
338
339                 do_lights(z, buttons);
340                 do_buttons(z, buttons, datawheel);
341         }
342
343         close_tranzport(z);
344
345         return 0;
346 }
347