ignore unpaired noteoff's when writing part of a MidiModel to a new source. in realit...
[ardour2.git] / libs / surfaces / tranzport / io_usb.cc
blobc4a004a160066735570d1e5dc37c8e4f4dc2a774
1 /*
2 * Copyright (C) 2006 Paul Davis
3 * Copyright (C) 2007 Michael Taht
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.
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.
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.
19 * */
21 #include <iostream>
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>
30 #include <tranzport_control_protocol.h>
32 #if !HAVE_TRANZPORT_KERNEL_DRIVER
34 using namespace ARDOUR;
35 using namespace std;
36 using namespace sigc;
37 using namespace PBD;
39 #include "i18n.h"
41 #include <pbd/abstract_ui.cc>
43 // I note that these usb specific open, close, probe, read routines are basically
44 // pure boilerplate and could easily be abstracted elsewhere
46 bool
47 TranzportControlProtocol::probe ()
49 struct usb_bus *bus;
50 struct usb_device *dev;
52 usb_init();
53 usb_find_busses();
54 usb_find_devices();
56 for (bus = usb_busses; bus; bus = bus->next) {
58 for(dev = bus->devices; dev; dev = dev->next) {
59 if (dev->descriptor.idVendor == VENDORID && dev->descriptor.idProduct == PRODUCTID) {
60 return true;
65 return false;
68 int
69 TranzportControlProtocol::open ()
71 struct usb_bus *bus;
72 struct usb_device *dev;
74 usb_init();
75 usb_find_busses();
76 usb_find_devices();
78 for (bus = usb_busses; bus; bus = bus->next) {
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);
89 cerr << _("Tranzport: no device detected") << endmsg;
90 return -1;
93 int
94 TranzportControlProtocol::open_core (struct usb_device* dev)
96 if (!(udev = usb_open (dev))) {
97 cerr << _("Tranzport: cannot open USB transport") << endmsg;
98 return -1;
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;
108 if (usb_set_configuration (udev, 1) < 0) {
109 cerr << _("Tranzport: cannot configure USB interface") << endmsg;
112 return 0;
116 TranzportControlProtocol::close ()
118 int ret = 0;
120 if (udev == 0) {
121 return 0;
124 if (usb_release_interface (udev, 0) < 0) {
125 cerr << _("Tranzport: cannot release interface") << endmsg;
126 ret = -1;
129 if (usb_close (udev)) {
130 cerr << _("Tranzport: cannot close device") << endmsg;
131 udev = 0;
132 ret = 0;
135 return ret;
138 int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override)
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;
158 return last_read_error;
163 TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
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);
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;
190 return val;
193 last_write_error = 0;
194 ++inflight;
196 return 0;
201 TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
203 #if MAX_RETRY > 1
204 int val;
205 int retry = 0;
206 if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
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);
212 if (retry == MAX_RETRY) {
213 printf("Too many retries on a tranzport write, aborting\n");
216 if (val < 0) {
217 printf("usb_interrupt_write failed: %d\n", val);
218 return val;
220 if (val != 8) {
221 printf("usb_interrupt_write failed: %d\n", val);
222 return -1;
224 ++inflight;
225 return 0;
226 #else
227 return (write_noretry(cmd,timeout_override));
228 #endif
232 #endif