enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / surfaces / tranzport / io_usb.cc
1 /*
2  *   Copyright (C) 2006 Paul Davis
3  *   Copyright (C) 2007 Michael Taht
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *   */
20
21 #include <iostream>
22
23 #define __STDC_FORMAT_MACROS
24 #include <inttypes.h>
25 #include <float.h>
26 #include <sys/time.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 #include <tranzport_control_protocol.h>
31
32 #if !HAVE_TRANZPORT_KERNEL_DRIVER
33
34 using namespace ARDOUR;
35 using namespace std;
36 using namespace sigc;
37 using namespace PBD;
38
39 #include "pbd/i18n.h"
40
41 #include <pbd/abstract_ui.cc>
42
43 // I note that these usb specific open, close, probe, read routines are basically
44 // pure boilerplate and could easily be abstracted elsewhere
45
46 bool
47 TranzportControlProtocol::probe ()
48 {
49         struct usb_bus *bus;
50         struct usb_device *dev;
51
52         usb_init();
53         usb_find_busses();
54         usb_find_devices();
55
56         for (bus = usb_busses; bus; bus = bus->next) {
57
58                 for(dev = bus->devices; dev; dev = dev->next) {
59                         if (dev->descriptor.idVendor == VENDORID && dev->descriptor.idProduct == PRODUCTID) {
60                                 return true;
61                         }
62                 }
63         }
64
65         return false;
66 }
67
68 int
69 TranzportControlProtocol::open ()
70 {
71         struct usb_bus *bus;
72         struct usb_device *dev;
73
74         usb_init();
75         usb_find_busses();
76         usb_find_devices();
77
78         for (bus = usb_busses; bus; bus = bus->next) {
79
80                 for(dev = bus->devices; dev; dev = dev->next) {
81                         if (dev->descriptor.idVendor != VENDORID)
82                                 continue;
83                         if (dev->descriptor.idProduct != PRODUCTID)
84                                 continue;
85                         return open_core (dev);
86                 }
87         }
88
89         cerr << _("Tranzport: no device detected") << endmsg;
90         return -1;
91 }
92
93 int
94 TranzportControlProtocol::open_core (struct usb_device* dev)
95 {
96         if (!(udev = usb_open (dev))) {
97                 cerr << _("Tranzport: cannot open USB transport") << endmsg;
98                 return -1;
99         }
100
101         if (usb_claim_interface (udev, 0) < 0) {
102                 cerr << _("Tranzport: cannot claim USB interface") << endmsg;
103                 usb_close (udev);
104                 udev = 0;
105                 return -1;
106         }
107
108         if (usb_set_configuration (udev, 1) < 0) {
109                 cerr << _("Tranzport: cannot configure USB interface") << endmsg;
110         }
111
112         return 0;
113 }
114
115 int
116 TranzportControlProtocol::close ()
117 {
118         int ret = 0;
119
120         if (udev == 0) {
121                 return 0;
122         }
123
124         if (usb_release_interface (udev, 0) < 0) {
125                 cerr << _("Tranzport: cannot release interface") << endmsg;
126                 ret = -1;
127         }
128
129         if (usb_close (udev)) {
130                 cerr << _("Tranzport: cannot close device") << endmsg;
131                 udev = 0;
132                 ret = 0;
133         }
134
135         return ret;
136 }
137
138 int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override)
139 {
140         last_read_error = usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, timeout_override);
141         switch(last_read_error) {
142         case -ENOENT:
143         case -ENXIO:
144         case -ECONNRESET:
145         case -ESHUTDOWN:
146         case -ENODEV:
147                 cerr << "Tranzport disconnected, errno: " << last_read_error;
148                 set_active(false);
149         case -ETIMEDOUT: // This is normal
150                 break;
151         default:
152 #if DEBUG_TRANZPORT
153                 cerr << "Got an unknown error on read:" << last_read_error "\n";
154 #endif
155                 break;
156         }
157
158         return last_read_error;
159 }
160
161
162 int
163 TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
164 {
165         int val;
166         if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
167         val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
168
169         if (val < 0 && val !=8) {
170 #if DEBUG_TRANZPORT
171                 printf("usb_interrupt_write failed: %d\n", val);
172 #endif
173                 last_write_error = val;
174                 switch(last_write_error) {
175                 case -ENOENT:
176                 case -ENXIO:
177                 case -ECONNRESET:
178                 case -ESHUTDOWN:
179                 case -ENODEV:
180                         cerr << "Tranzport disconnected, errno: " << last_write_error;
181                         set_active(false);
182                 case -ETIMEDOUT: // This is normal
183                         break;
184                 default:
185 #if DEBUG_TRANZPORT
186                         cerr << "Got an unknown error on read:" << last_write_error "\n";
187 #endif
188                         break;
189                 }
190                 return val;
191         }
192
193         last_write_error = 0;
194         ++inflight;
195
196         return 0;
197
198 }
199
200 int
201 TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
202 {
203 #if MAX_RETRY > 1
204         int val;
205         int retry = 0;
206         if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
207
208         while((val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout))!=8 && retry++ < MAX_RETRY) {
209                 printf("usb_interrupt_write failed, retrying: %d\n", val);
210         }
211
212         if (retry == MAX_RETRY) {
213                 printf("Too many retries on a tranzport write, aborting\n");
214         }
215
216         if (val < 0) {
217                 printf("usb_interrupt_write failed: %d\n", val);
218                 return val;
219         }
220         if (val != 8) {
221                 printf("usb_interrupt_write failed: %d\n", val);
222                 return -1;
223         }
224         ++inflight;
225         return 0;
226 #else
227         return (write_noretry(cmd,timeout_override));
228 #endif
229
230 }
231
232 #endif