0aa82d4b115632767e6fd55b7531f472c29fa22c
[owTools.git] / src / owUSBInterface.cpp
1 // Copyright (c) 2017, Tobias Mueller tm(at)tm3d.de
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //  * Redistributions of source code must retain the above copyright
9 //    notice, this list of conditions and the following disclaimer.
10 //  * Redistributions in binary form must reproduce the above copyright
11 //    notice, this list of conditions and the following disclaimer in the
12 //    documentation and/or other materials provided with the
13 //    distribution.
14 //  * All advertising materials mentioning features or use of this
15 //    software must display the following acknowledgement: This product
16 //    includes software developed by tm3d.de and its contributors.
17 //  * Neither the name of tm3d.de nor the names of its contributors may
18 //    be used to endorse or promote products derived from this software
19 //    without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33
34 #include "owUSBInterface.h"
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <unistd.h>
39 #include <pthread.h>
40 #include <memory.h>
41
42
43
44
45 extern "C" {
46 #include "libusbds2490.h"
47 }
48
49
50
51
52 namespace usb_1w {
53         
54         
55 #define FALSE 0
56 #define TRUE 1
57 int usb_num_devices = -1;
58 usb_dev_handle *usb_dev_handle_list[20];
59 //static SMALLINT usbhnd_init = 0;
60 struct usb_device *usb_dev_list[20];
61 static void DS2490Discover(void)
62 {
63         struct usb_bus *bus;
64         struct usb_device *dev;
65
66         // initialize USB subsystem
67 #ifdef LIBUSB_DEBUG_DISABLE  // Use this define at compile time to turn off LIBUSB debug info
68    usb_set_debug(0);
69 #endif
70    usb_init();
71    usb_find_busses();
72    usb_find_devices();
73
74    usb_num_devices = 0; // avoid port zero to make it look like other builds
75
76         for (bus = usb_get_busses(); bus; bus = bus->next) 
77         {
78                                 
79                 for (dev = bus->devices; dev; dev = dev->next) 
80                 {
81                         //printf("%04X:%04X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
82                         if (dev->descriptor.idVendor == 0x04FA &&
83                                  dev->descriptor.idProduct == 0x2490) 
84                         {
85                                 //printf("DS2490Discover-find\n");
86                                 usb_dev_list[++usb_num_devices] = dev;
87                                 
88                         }
89                 }
90         }
91 }
92
93
94 uint8_t AdapterRecover(usb_dev_handle *hDevice)
95 {
96    // detect DS2490 and set it up
97    if (DS2490Detect(hDevice))
98    {
99       //USBSpeed[portnum] = MODE_NORMAL; // current DS2490 1-Wire Net communication speed
100       //USBLevel[portnum] = MODE_NORMAL; // current DS2490 1-Wire Net level
101       return TRUE;
102    }
103    else
104    {
105       //OWERROR(OWERROR_SYSTEM_RESOURCE_INIT_FAILED);
106       return FALSE;
107    }
108 }
109
110 }
111
112 using namespace usb_1w;
113 int id[8];
114 int first=1;
115
116 int owUSBInterface::InitAdapter(uint8_t pin){
117     if(!usbhnd_init)  // check to see the USB bus has been setup properly
118     {
119             // discover all DS2490s on USB bus...
120             DS2490Discover();
121         usbhnd_init = 1;
122     }
123         if (usb_num_devices==0) return -1;
124
125     // check to see if the portnumber is valid
126     if ((usb_num_devices <pin) || (pin == 0)) 
127     {
128                 // error - Attempted to select invalid port number
129         log->set(OWLOG_ERROR,"OWERROR_LIBUSB_NO_ADAPTER_FOUND");
130             return -1;
131     }
132
133     // check to see if opening the device is valid
134     if (hDevice!= NULL) 
135         {
136                 // error - USB Device already open
137                 log->set(OWLOG_ERROR,"OWERROR_LIBUSB_DEVICE_ALREADY_OPENED");
138         return -1;
139     }
140
141     // open the device
142     hDevice = usb_open(usb_dev_list[pin]);
143     if (hDevice == NULL) 
144     {
145         // Failed to open usb device
146                 log->set(OWLOG_ERROR,"OWERROR_LIBUSB_OPEN_FAILED");
147                 return -1;
148     }
149
150     // set the configuration
151     if (usb_set_configuration(hDevice, 1)) 
152     {
153         // Failed to set configuration
154                 log->set(OWLOG_ERROR,"OWERROR_LIBUSB_SET_CONFIGURATION_ERROR");
155         usb_close(hDevice); // close handle
156             return -2;
157     }
158
159     // claim the interface
160     if (usb_claim_interface(hDevice, 0)) 
161     {
162         // Failed to claim interface
163             //printf("%s\n", usb_strerror());
164                 log->set(OWLOG_ERROR,"OWERROR_LIBUSB_CLAIM_INTERFACE_ERROR");
165             usb_close(hDevice); // close handle
166                 return -1;
167         }
168
169         // set the alt interface
170         if (usb_set_altinterface(hDevice, 3)) 
171         {
172                 // Failed to set altinterface
173                 //printf("%s\n", usb_strerror());
174                 log->set(OWLOG_ERROR,"OWERROR_LIBUSB_SET_ALTINTERFACE_ERROR");
175                 usb_release_interface(hDevice, 0); // release interface
176                 usb_close(hDevice);   // close handle
177                 return -1;
178         }
179
180    
181     // clear USB endpoints before doing anything with them.
182         usb_clear_halt(hDevice, DS2490_EP3);
183         usb_clear_halt(hDevice, DS2490_EP2);
184         usb_clear_halt(hDevice, DS2490_EP1);
185
186     // verify adapter is working
187     if (!AdapterRecover(hDevice))
188     {
189                 log->set(OWLOG_ERROR,"Adapter don't work");
190                 usb_release_interface(hDevice, 0); // release interface
191                 usb_close(hDevice);   // close handle
192         return -1;
193     }
194
195     // reset the 1-Wire
196     Reset();
197
198     return 1;
199  }
200 int owUSBInterface::Reset() {
201    SETUP_PACKET setup;
202    SMALLINT present,vpp;
203    SMALLINT ret = 0;
204
205    // construct command
206    setup.RequestTypeReservedBits = 0x40;
207    setup.Request = COMM_CMD;
208    setup.Value = COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE;
209    setup.Index =  ONEWIREBUSSPEED_REGULAR;// ONEWIREBUSSPEED_FLEXIBLE;
210    setup.Length = 0;
211    setup.DataOut = FALSE;
212    // call the libusb driver
213    ret = usb_control_msg(hDevice, 
214                          setup.RequestTypeReservedBits, 
215                          setup.Request, 
216                          setup.Value, 
217                          setup.Index, 
218                          NULL, 
219                          setup.Length, 
220                          TIMEOUT_LIBUSB);
221    if (ret < 0)
222    {
223       // failure
224       log->set(OWLOG_ERROR,"OWERROR_RESET_FAILED");
225       //AdapterRecover(portnum);
226       return FALSE;
227    }
228    else
229    {
230       // extra delay for alarming DS1994/DS2404 complience
231      // if ((FAMILY_CODE_04_ALARM_TOUCHRESET_COMPLIANCE) && (USBSpeed[portnum] != MODE_OVERDRIVE))
232      //    msDelay(5);
233
234       // success, check for shorts
235       if (DS2490ShortCheck(hDevice, &present,&vpp))
236       {
237          //USBVpp[portnum] = vpp;     
238          return present;
239       }
240       else
241       {
242        log->set(OWLOG_ERROR,"OWERROR_OW_SHORTED");
243          // short occuring
244          usleep(300);
245          //AdapterRecover(portnum);
246          return FALSE;
247       }
248    }
249 }
250
251
252 uint8_t owUSBInterface::sendrecivBit(uint8_t bit) {
253         SETUP_PACKET setup;
254         ushort nBytes;   
255         uchar buf[2];
256         SMALLINT ret = 0;
257
258         // set to do touchbit
259         setup.RequestTypeReservedBits = 0x40;
260         setup.Request = COMM_CMD;
261         setup.Value = COMM_BIT_IO | COMM_IM | ((bit) ? COMM_D : 0);
262         setup.Index = 0;  
263         setup.Length = 0;
264         setup.DataOut = FALSE;
265
266    // call the libusb driver
267    ret = usb_control_msg(hDevice, 
268                          setup.RequestTypeReservedBits, 
269                          setup.Request, 
270                          setup.Value, 
271                          setup.Index, 
272                          NULL, 
273                          setup.Length, 
274                          TIMEOUT_LIBUSB);
275    if (ret < 0)
276    {
277       // failure
278       log->set(OWLOG_ERROR,"OWERROR_ADAPTER_ERROR");
279       AdapterRecover(hDevice);
280       return 0;
281    }
282    else
283    {
284       // success, read the result
285       nBytes = 1;
286       if (DS2490Read(hDevice, buf, &nBytes)) {
287                 usleep(70);
288          return buf[0];
289         }
290       else
291       {
292          log->set(OWLOG_ERROR,"OWERROR_ADAPTER_ERROR");
293          AdapterRecover(hDevice);
294          return 0;
295       }
296    }
297 }
298
299 uint8_t owUSBInterface::sendrecivByte(uint8_t byte) {
300         SETUP_PACKET setup;
301     ushort nBytes;   
302         uchar buf[2];
303         SMALLINT ret = 0;
304
305         // set to do touchbyte
306         setup.RequestTypeReservedBits = 0x40;
307         setup.Request = COMM_CMD;
308         setup.Value = COMM_BYTE_IO | COMM_IM;
309         setup.Index = byte & 0xFF;  
310         setup.Length = 0;
311         setup.DataOut = FALSE;
312
313         // call the libusb driver
314         ret = usb_control_msg(hDevice, 
315                          setup.RequestTypeReservedBits, 
316                          setup.Request, 
317                          setup.Value, 
318                          setup.Index, 
319                          NULL, 
320                          setup.Length, 
321                          TIMEOUT_LIBUSB);
322    if (ret < 0)
323    {
324       // failure
325       log->set(OWLOG_ERROR,"OWERROR_ADAPTER_ERROR");
326       AdapterRecover(hDevice);
327       return 0;
328    }
329    else
330    {
331       // success, read the result
332       nBytes = 1;
333
334       if (DS2490Read(hDevice, buf, &nBytes)) {
335          usleep(80);
336          return buf[0];
337          }
338       else
339       {
340          log->set(OWLOG_ERROR,"OWERROR_ADAPTER_ERROR");
341          AdapterRecover(hDevice);
342          return 0;
343       }
344    }
345 }
346
347 void owUSBInterface::ReleaseAdapter() {
348         usb_release_interface(hDevice, 0);
349         usb_close(hDevice);
350         hDevice = NULL;
351 }