Check in
[owTools.git] / src / libusbds2490.c
1 //---------------------------------------------------------------------------\r
2 // Copyright (C) 2004 Dallas Semiconductor MAXIM Corporation, All Rights Reserved.\r
3 //\r
4 // Permission is hereby granted, free of charge, to any person obtaining a\r
5 // copy of this software and associated documentation files (the "Software"),\r
6 // to deal in the Software without restriction, including without limitation\r
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
8 // and/or sell copies of the Software, and to permit persons to whom the\r
9 // Software is furnished to do so, subject to the following conditions:\r
10 //\r
11 // The above copyright notice and this permission notice shall be included\r
12 // in all copies or substantial portions of the Software.\r
13 //\r
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
16 // MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES\r
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r
20 // OTHER DEALINGS IN THE SOFTWARE.\r
21 //\r
22 // Except as contained in this notice, the name of Dallas Semiconductor MAXIM\r
23 // shall not be used except as stated in the Dallas Semiconductor MAXIM\r
24 // Branding Policy.\r
25 //---------------------------------------------------------------------------\r
26 //\r
27 //  libusblds2490.c - DS2490 utility functions for Windows.\r
28 //                    (Requires libusb http://libusb.sourceforge.net\r
29 //                    or http://libusb-win32.sourceforge.net)\r
30 //\r
31 //  Version: \r
32 //\r
33 \r
34 //#include "ownet.h"\r
35 #include "libusbds2490.h"\r
36 #include <string.h>\r
37 #include <stdio.h>\r
38 \r
39 #define TRUE 1\r
40 #define FALSE 0\r
41 #define OWERROR_ADAPTER_ERROR                   110\r
42 #define OWERROR(err) printf("%i",err);\r
43 \r
44 #define MAX_PORTNUM 20\r
45 // handles for the USB ports\r
46 extern struct usb_dev_handle *usb_dev_handle_list[MAX_PORTNUM];\r
47 \r
48 // global DS2490 state\r
49 SMALLINT USBLevel[MAX_PORTNUM]; \r
50 SMALLINT USBSpeed[MAX_PORTNUM]; \r
51 SMALLINT USBVersion[MAX_PORTNUM]; \r
52 SMALLINT USBVpp[MAX_PORTNUM]; \r
53 \r
54 long msGettick(void)\r
55 {\r
56 #if USE_WINDOWS_TIME\r
57    return GetTickCount();\r
58 #else\r
59    struct timezone tmzone;\r
60    struct timeval  tmval;\r
61    long ms;\r
62 \r
63    gettimeofday(&tmval,&tmzone);\r
64    ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000;\r
65    return ms;\r
66 #endif\r
67 }\r
68 \r
69 //---------------------------------------------------------------------------\r
70 // Attempt to resync and detect a DS2490\r
71 //\r
72 // 'portnum'    - number 0 to MAX_PORTNUM-1.  This number was provided to\r
73 //                OpenCOM to indicate the port number.\r
74 //\r
75 // Returns:  TRUE  - DS2490 detected successfully\r
76 //           FALSE - Could not detect DS2490\r
77 //\r
78 SMALLINT DS2490Detect(usb_dev_handle *hDevice)\r
79 {\r
80    SMALLINT present,vpp;\r
81    SETUP_PACKET setup;\r
82 \r
83    // reset the DS2490\r
84         //printf("DS2490Detect\n");\r
85    DS2490Reset(hDevice);\r
86 \r
87    // set the strong pullup duration to infinite\r
88    setup.RequestTypeReservedBits = 0x40;\r
89    setup.Request = COMM_CMD;\r
90    setup.Value = COMM_SET_DURATION | COMM_IM;\r
91    setup.Index = 0x0000;\r
92    setup.Length = 0;\r
93    setup.DataOut = FALSE;\r
94    // call the libusb driver\r
95    /*ret =*/ usb_control_msg(hDevice,\r
96                          setup.RequestTypeReservedBits,\r
97                          setup.Request,\r
98                          setup.Value,\r
99                          setup.Index,\r
100                          NULL,\r
101                          setup.Length,\r
102                          TIMEOUT_LIBUSB);\r
103 \r
104    // set the 12V pullup duration to 512us\r
105    setup.RequestTypeReservedBits = 0x40;\r
106    setup.Request = COMM_CMD;\r
107    setup.Value = COMM_SET_DURATION | COMM_IM | COMM_TYPE;\r
108    setup.Index = 0x0040;\r
109    setup.Length = 0;\r
110    setup.DataOut = FALSE;\r
111    // call the libusb driver\r
112   /* ret = */usb_control_msg(hDevice, \r
113                          setup.RequestTypeReservedBits, \r
114                          setup.Request, \r
115                          setup.Value, \r
116                          setup.Index, \r
117                          NULL, \r
118                          setup.Length, \r
119                          TIMEOUT_LIBUSB);\r
120  \r
121    // disable strong pullup, but leave program pulse enabled (faster)\r
122    setup.RequestTypeReservedBits = 0x40;\r
123    setup.Request = MODE_CMD;\r
124    setup.Value = MOD_PULSE_EN;\r
125    setup.Index = ENABLEPULSE_PRGE; \r
126    setup.Length = 0x00;\r
127    setup.DataOut = FALSE;\r
128    // call the libusb driver\r
129    /*ret = */usb_control_msg(hDevice, \r
130                          setup.RequestTypeReservedBits, \r
131                          setup.Request, \r
132                          setup.Value, \r
133                          setup.Index, \r
134                          NULL, \r
135                          setup.Length, \r
136                          TIMEOUT_LIBUSB);\r
137 \r
138    // return result of short check\r
139    return DS2490ShortCheck(hDevice,&present,&vpp);\r
140 }\r
141 \r
142 \r
143 //---------------------------------------------------------------------------\r
144 // Check to see if there is a short on the 1-Wire bus. Used to stop \r
145 // communication with the DS2490 while the short is in effect to not\r
146 // overrun the buffers.\r
147 //\r
148 // '*present' - flag set (1) if device presence detected\r
149 // '*vpp' - flag set (1) if Vpp programming voltage detected\r
150 //\r
151 // Returns:  TRUE  - DS2490 1-Wire is NOT shorted\r
152 //           FALSE - Could not detect DS2490 or 1-Wire shorted\r
153 //\r
154 SMALLINT DS2490ShortCheck(usb_dev_handle *hDevice, SMALLINT *present, SMALLINT *vpp)\r
155 {\r
156    STATUS_PACKET status;\r
157    uchar nResultRegisters;\r
158    uint8_t i;\r
159 \r
160    // get the result registers (if any)\r
161    if (!DS2490GetStatus(hDevice, &status, &nResultRegisters))\r
162       return FALSE;\r
163 \r
164    // get vpp present flag\r
165    *vpp = ((status.StatusFlags & STATUSFLAGS_12VP) != 0);\r
166 \r
167    //   Check for short\r
168    if(status.CommBufferStatus != 0)\r
169    {    \r
170       return FALSE;\r
171    }\r
172    else\r
173    {  \r
174       // check for short\r
175       for (i = 0; i < nResultRegisters; i++)\r
176       { \r
177          // check for SH bit (0x02), ignore 0xA5\r
178          if (status.CommResultCodes[i] & COMMCMDERRORRESULT_SH)\r
179          {      \r
180             // short detected\r
181             return FALSE; \r
182          }\r
183       }\r
184    }\r
185 \r
186    // check for No 1-Wire device condition\r
187    *present = TRUE;\r
188    // loop through result registers\r
189    for (i = 0; i < nResultRegisters; i++)\r
190    {   \r
191       // only check for error conditions when the condition is not a ONEWIREDEVICEDETECT\r
192       if (status.CommResultCodes[i] != ONEWIREDEVICEDETECT)\r
193       {   \r
194          // check for NRS bit (0x01)\r
195          if (status.CommResultCodes[i] & COMMCMDERRORRESULT_NRS)\r
196          {   \r
197             // empty bus detected\r
198             *present = FALSE;\r
199          }\r
200       }\r
201    }\r
202 \r
203    return TRUE;\r
204 }\r
205 \r
206 \r
207 //---------------------------------------------------------------------------\r
208 // Stop any on-going pulses\r
209 //\r
210 // Returns:  TRUE  - pulse stopped\r
211 //           FALSE - Could not stop pulse\r
212 //\r
213 SMALLINT DS2490HaltPulse(usb_dev_handle *hDevice)\r
214 {\r
215    STATUS_PACKET status;\r
216    uchar nResultRegisters;\r
217    SETUP_PACKET setup;\r
218    SMALLINT ret;\r
219    long limit;\r
220 \r
221    \r
222    // set a time limit\r
223    limit = msGettick() + 300;\r
224    // loop until confirm pulse has ended or timeout\r
225    do\r
226    {\r
227       // HalExecWhenIdle, Resume Execution to stop an infinite pulse\r
228       \r
229       // HalExecWhenIdle\r
230       setup.RequestTypeReservedBits = 0x40;\r
231       setup.Request = CONTROL_CMD;\r
232       setup.Value = CTL_HALT_EXE_IDLE;\r
233       setup.Index = 0x00;\r
234       setup.Length = 0x00;\r
235       setup.DataOut = FALSE;\r
236 \r
237       // call the libusb driver\r
238       ret = usb_control_msg(hDevice, \r
239                             setup.RequestTypeReservedBits, \r
240                             setup.Request, \r
241                             setup.Value, \r
242                             setup.Index, \r
243                             NULL, \r
244                             setup.Length, \r
245                             TIMEOUT_LIBUSB);\r
246     \r
247       if (ret < 0)\r
248       {\r
249          // failure\r
250          break;\r
251       }\r
252 \r
253       // Resume Execution   \r
254       setup.RequestTypeReservedBits = 0x40;\r
255       setup.Request = CONTROL_CMD;\r
256       setup.Value = CTL_RESUME_EXE;\r
257       setup.Index = 0x00;\r
258       setup.Length = 0x00;\r
259       setup.DataOut = FALSE;\r
260 \r
261       // call the libusb driver\r
262       ret = usb_control_msg(hDevice, \r
263                             setup.RequestTypeReservedBits, \r
264                             setup.Request, \r
265                             setup.Value, \r
266                             setup.Index, \r
267                             NULL, \r
268                             setup.Length, \r
269                             TIMEOUT_LIBUSB);\r
270    \r
271       if (ret < 0)\r
272       {\r
273          // failure\r
274          break;\r
275       }\r
276 \r
277       // read the status to see if the pulse has been stopped\r
278       if (!DS2490GetStatus(hDevice, &status, &nResultRegisters))\r
279       {\r
280          // failure\r
281          break;\r
282       }\r
283       else\r
284       {\r
285          // check the SPU flag\r
286          if ((status.StatusFlags & STATUSFLAGS_SPUA) == 0)\r
287          {\r
288             // success\r
289             // disable both pulse types\r
290             setup.RequestTypeReservedBits = 0x40;\r
291             setup.Request = MODE_CMD;\r
292             setup.Value = MOD_PULSE_EN;\r
293             setup.Index = 0;\r
294             setup.Length = 0x00;\r
295             setup.DataOut = FALSE;\r
296             // call the libusb driver\r
297             ret = usb_control_msg(hDevice, \r
298                                   setup.RequestTypeReservedBits, \r
299                                   setup.Request, \r
300                                   setup.Value, \r
301                                   setup.Index, \r
302                                   NULL, \r
303                                   setup.Length, \r
304                                   TIMEOUT_LIBUSB);\r
305 \r
306             return TRUE;\r
307          }\r
308       }\r
309    }\r
310    while (limit > msGettick());\r
311 \r
312    return FALSE;\r
313 }\r
314 \r
315 //---------------------------------------------------------------------------\r
316 // Description: Gets the status of the DS2490 device\r
317 // Input:       hDevice - the handle to the DS2490 device\r
318 //              pStatus - the Status Packet to be filled with data\r
319 //              pResultSize - the number of result register codes returned\r
320 //\r
321 // Returns:     FALSE on failure, TRUE on success\r
322 //\r
323 SMALLINT DS2490GetStatus(usb_dev_handle *hDevice, STATUS_PACKET *status, uchar *pResultSize)\r
324 {\r
325    // buffer to retrieve status\r
326    uchar buffer[32];\r
327    uint8_t i = 0;\r
328    SMALLINT bufferlength = 0;\r
329 \r
330    // initialize buffer\r
331    memset(&buffer[0],0x00,32);\r
332    // get status buffer\r
333    bufferlength = usb_bulk_read(hDevice,DS2490_EP1,&buffer[0],32,TIMEOUT_LIBUSB);\r
334 \r
335    if (bufferlength < 0)\r
336    {\r
337       OWERROR(OWERROR_ADAPTER_ERROR);\r
338       return FALSE;\r
339    }\r
340 \r
341    // make status packet from return buffer\r
342    status->EnableFlags = buffer[0];\r
343    status->OneWireSpeed = buffer[1];\r
344    status->StrongPullUpDuration = buffer[2];\r
345    status->ProgPulseDuration = buffer[3];\r
346    status->PullDownSlewRate = buffer[4];\r
347    status->Write1LowTime = buffer[5];\r
348    status->DSOW0RecoveryTime = buffer[6];\r
349    status->Reserved1 = buffer[7];\r
350    status->StatusFlags = buffer[8];\r
351    status->CurrentCommCmd1 = buffer[9];\r
352    status->CurrentCommCmd2 = buffer[10];\r
353    status->CommBufferStatus = buffer[11];  \r
354    status->WriteBufferStatus = buffer[12]; \r
355    status->ReadBufferStatus = buffer[13];\r
356    status->Reserved2 = buffer[14];\r
357    status->Reserved3 = buffer[15];\r
358 \r
359    // take care for CommResultCodes (if they exist)\r
360    if (bufferlength > 15)\r
361    {\r
362        for (i=0; i<16; i++)  \r
363        {\r
364           status->CommResultCodes[i] = buffer[16 + i];\r
365          }\r
366        *pResultSize = bufferlength - 16; // This should be the size of CommResultCodes...\r
367    }\r
368    else\r
369    {\r
370        *pResultSize = 0;\r
371    }\r
372    return TRUE;\r
373 }\r
374 \r
375 \r
376 //---------------------------------------------------------------------------\r
377 // Description: Perfroms a hardware reset of the DS2490 equivalent to a \r
378 //              power-on reset\r
379 // Input:       hDevice - the handle to the DS2490 device\r
380 // Returns:     FALSE on failure, TRUE on success\r
381 // Error Codes: DS2490COMM_ERR_USBDEVICE\r
382 //\r
383 SMALLINT DS2490Reset(usb_dev_handle *hDevice)\r
384 {\r
385    SETUP_PACKET setup;\r
386    SMALLINT ret = 0;\r
387 \r
388    // setup for reset\r
389    setup.RequestTypeReservedBits = 0x40;\r
390    setup.Request = CONTROL_CMD;\r
391    setup.Value = CTL_RESET_DEVICE;\r
392    setup.Index = 0x00;\r
393    setup.Length = 0x00;\r
394    setup.DataOut = FALSE;\r
395    // call the libusb driver\r
396    ret = usb_control_msg(hDevice, \r
397                          setup.RequestTypeReservedBits, \r
398                          setup.Request, \r
399                          setup.Value, \r
400                          setup.Index, \r
401                          NULL, \r
402                          setup.Length, \r
403                          TIMEOUT_LIBUSB);\r
404    if (ret < 0)\r
405    {\r
406       OWERROR(OWERROR_ADAPTER_ERROR);\r
407       return FALSE;\r
408    }\r
409    return TRUE;\r
410 }\r
411 \r
412 \r
413 //---------------------------------------------------------------------------\r
414 // Description: Reads data from EP3\r
415 // Input:       hDevice - the handle to the DS2490 device\r
416 //              buffer - the size must be >= nBytes\r
417 //              pnBytes - the number of bytes to read from the device\r
418 // Returns:     FALSE on failure, TRUE on success\r
419 //\r
420 SMALLINT DS2490Read(usb_dev_handle *hDevice, uchar *buffer, ushort *pnBytes)\r
421 {\r
422 \r
423    // Synchronous read:\r
424    SMALLINT numOfBytesToRead = *pnBytes;\r
425         int nBytes = 0;\r
426 \r
427    // read\r
428    nBytes = usb_bulk_read(hDevice,         // handle\r
429                            DS2490_EP3,      // which endpoint to read from\r
430                            buffer,          // buffer to contain read results\r
431                            numOfBytesToRead,        // number of bytes to read \r
432                            TIMEOUT_LIBUSB); // libusb timeout\r
433 \r
434    if (nBytes < 0)\r
435    {\r
436            OWERROR(OWERROR_ADAPTER_ERROR);\r
437            return FALSE;\r
438    }\r
439    *pnBytes = (ushort)nBytes;\r
440    return TRUE;\r
441 }\r
442 \r
443 //---------------------------------------------------------------------------\r
444 // Description: Writes data to EP2\r
445 // Input:       hDevice - the handle to the DS2490 device\r
446 //              buffer - the size must be >= nBytes\r
447 //              pnBytes - the number of bytes to write to the device\r
448 // Returns:     FALSE on failure, TRUE on success\r
449 //\r
450 SMALLINT DS2490Write(usb_dev_handle *hDevice, uchar *buffer, ushort *pnBytes)\r
451 {\r
452    // Synchronous write:\r
453    // assume enough room for write\r
454    int  nBytes = 0;\r
455    int numOfBytesToRead = *pnBytes;\r
456 \r
457    // write\r
458    nBytes = usb_bulk_write(hDevice,         // handle\r
459                            DS2490_EP2,      // which endpoint to write\r
460                            buffer,          // buffer to write to endpoint\r
461                            numOfBytesToRead,        // number of bytes to write\r
462                            TIMEOUT_LIBUSB); // libusb timeout\r
463    \r
464    if (nBytes < 0)\r
465    {\r
466       OWERROR(OWERROR_ADAPTER_ERROR);\r
467       return FALSE;\r
468    }\r
469 \r
470    *pnBytes = (ushort)nBytes;\r
471    return TRUE;\r
472 }\r
473 \r