1 //---------------------------------------------------------------------------
2 // Copyright (C) 2001 Matthew Dharm, All Rights Reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
18 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Matthew is not activily supporting this code but can be reached at:
23 // mailto:mdharm-usb@one-eyed-alien.net
24 //---------------------------------------------------------------------------
25 //
26 // usb_drv.c - General 1-Wire link layer for the DS2490 on Linux
27 //
28 // Version: 3.00B
29 //
30
31 #include "ownet.h"
32 #include "usb.h"
33 #include <errno.h>
34
35 #define CONTROL_CMD 0x00
36 #define COMM_CMD 0x01
37 #define MODE_CMD 0x02
38 #define TEST_CMD 0x03
39
40 #define MOD_SPEED_CHANGE_EN 0x0001
41 #define MOD_1WIRE_SPEED 0x0002
42
43 #define TIMEOUT_VALUE 5000
44
45 /* the structure we'll use to access other devices */
46 extern struct usb_dev_handle *usb_dev_handle_list[MAX_PORTNUM];
47
48 // exportable link-level functions
49 SMALLINT owTouchReset(int);
50 SMALLINT owTouchBit(int,SMALLINT);
51 SMALLINT owTouchByte(int,SMALLINT);
52 SMALLINT owWriteByte(int,SMALLINT);
53 SMALLINT owReadByte(int);
54 SMALLINT owSpeed(int,SMALLINT);
55 SMALLINT owLevel(int,SMALLINT);
56 SMALLINT owProgramPulse(int);
57 void msDelay(int);
58 long msGettick(void);
59 SMALLINT hasPowerDelivery(int);
60 SMALLINT hasOverDrive(int);
61 SMALLINT hasProgramPulse(int);
62 SMALLINT owWriteBytePower(int,SMALLINT);
63 SMALLINT owReadBitPower(int, SMALLINT);
64
65 //--------------------------------------------------------------------------
66 // Reset all of the devices on the 1-Wire Net and return the result.
67 //
68 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
69 // indicate the symbolic port number.
70 //
71 // Returns: TRUE(1): presense pulse(s) detected, device(s) reset
72 // FALSE(0): no presense pulses detected
73 //
owTouchReset(int portnum)74 int owTouchReset(int portnum)
75 {
76 int result;
77 unsigned char buffer[0x20];
78
79 /* issue the 1-wire reset */
80 result = usb_control_msg(usb_dev_handle_list[portnum], 0x40,
81 COMM_CMD, 0x0043, 0x0000, NULL, 0x0, TIMEOUT_VALUE);
82 //printf("result is %d\n", result);
83
84 /* repeat until the unit is not idle */
85 do {
86 /* get the status */
87 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81,
88 buffer, 0x20, TIMEOUT_VALUE);
89 //printf("result is %d\n", result);
90
91 //for (result = 0; result < 0x20; result++) {
92 // printf("%02X: %02X\n", result, buffer[result]);
93 //}
94 } while (!(buffer[0x08] & 0x20) && !(result < 0));
95
96 if (result < 0)
97 return FALSE;
98
99 if (buffer[0x10] & 0x01) {
100 return FALSE;
101 } else {
102 return TRUE;
103 }
104 }
105
106 //--------------------------------------------------------------------------
107 // Send 1 bit of communication to the 1-Wire Net and return the
108 // result 1 bit read from the 1-Wire Net. The parameter 'sendbit'
109 // least significant bit is used and the least significant bit
110 // of the result is the return bit.
111 //
112 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
113 // indicate the symbolic port number.
114 // 'sendbit' - the least significant bit is the bit to send
115 //
116 // Returns: 0: 0 bit read from sendbit
117 // 1: 1 bit read from sendbit
118 //
owTouchBit(int portnum,SMALLINT sendbit)119 int owTouchBit(int portnum, SMALLINT sendbit)
120 {
121 int result;
122 unsigned char retval;
123 unsigned char buffer[0x20];
124
125 /* issue the bit i/o command */
126 result = usb_control_msg(usb_dev_handle_list[portnum], 0x40,
127 COMM_CMD, 0x0021 | (sendbit << 3), 0x0000, NULL, 0x0, TIMEOUT_VALUE);
128 //printf("result is %d\n", result);
129
130 /* repeat until the unit is not idle */
131 do {
132 /* get the status */
133 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81,
134 buffer, 0x20, TIMEOUT_VALUE);
135 //printf("result is %d\n", result);
136
137 //for (result = 0; result < 0x20; result++) {
138 // printf("%02X: %02X\n", result, buffer[result]);
139 //}
140 } while (!(buffer[0x08] & 0x20) && !(result < 0));
141
142 /* get the data */
143 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x83,
144 &retval, 0x1, 1000);
145 if (result == -1) {
146 printf ("owTouchBit: clearing halt\n");
147 usb_clear_halt(usb_dev_handle_list[portnum], 0x83);
148 }
149
150
151 /* return the data */
152 return retval;
153 }
154
155 //--------------------------------------------------------------------------
156 // Send 8 bits of communication to the 1-Wire Net and return the
157 // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte'
158 // least significant 8 bits are used and the least significant 8 bits
159 // of the result is the return byte.
160 //
161 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
162 // indicate the symbolic port number.
163 // 'sendbyte' - 8 bits to send (least significant byte)
164 //
165 // Returns: 8 bytes read from sendbyte
166 //
owTouchByte(int portnum,SMALLINT sendbyte)167 int owTouchByte(int portnum, SMALLINT sendbyte)
168 {
169 int result;
170 unsigned char retval;
171 unsigned char buffer[0x20];
172
173 /* issue the byte i/o command */
174 result = usb_control_msg(usb_dev_handle_list[portnum], 0x40,
175 COMM_CMD, 0x0053, 0x0000 | sendbyte, NULL, 0x0, TIMEOUT_VALUE);
176 //printf("result is %d\n", result);
177
178 /* repeat until the unit is not idle */
179 do {
180 /* get the status */
181 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81,
182 buffer, 0x20, TIMEOUT_VALUE);
183 //printf("result is %d\n", result);
184
185 //for (result = 0; result < 0x20; result++) {
186 // printf("%02X: %02X\n", result, buffer[result]);
187 //}
188 } while (!(buffer[0x08] & 0x20) && !(result < 0));
189
190 /* get the data */
191 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x83,
192 &retval, 0x1, 1000);
193 if (result == -1) {
194 printf ("owTouchByte: clearing halt\n");
195 usb_clear_halt(usb_dev_handle_list[portnum], 0x83);
196 }
197
198 /* return the data */
199 return retval;
200 }
201
202 //--------------------------------------------------------------------------
203 // Send 8 bits of communication to the 1-Wire Net and verify that the
204 // 8 bits read from the 1-Wire Net is the same (write operation).
205 // The parameter 'sendbyte' least significant 8 bits are used.
206 //
207 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
208 // indicate the symbolic port number.
209 // 'sendbyte' - 8 bits to send (least significant byte)
210 //
211 // Returns: TRUE: bytes written and echo was the same
212 // FALSE: echo was not the same
213 //
owWriteByte(int portnum,SMALLINT sendbyte)214 int owWriteByte(int portnum, SMALLINT sendbyte)
215 {
216 return (owTouchByte(portnum,sendbyte) == sendbyte) ? TRUE : FALSE;
217 }
218
219 //--------------------------------------------------------------------------
220 // Send 8 bits of read communication to the 1-Wire Net and and return the
221 // result 8 bits read from the 1-Wire Net.
222 //
223 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
224 // indicate the symbolic port number.
225 //
226 // Returns: 8 bytes read from 1-Wire Net
227 //
owReadByte(int portnum)228 int owReadByte(int portnum)
229 {
230 return owTouchByte(portnum,0xFF);
231 }
232
233 //--------------------------------------------------------------------------
234 // Set the 1-Wire Net communucation speed.
235 //
236 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
237 // indicate the symbolic port number.
238 // 'new_speed' - new speed defined as
239 // MODE_NORMAL 0x00
240 // MODE_OVERDRIVE 0x01
241 //
242 // Returns: current 1-Wire Net speed
243 //
owSpeed(int portnum,SMALLINT new_speed)244 int owSpeed(int portnum, SMALLINT new_speed)
245 {
246 int result;
247 unsigned char retval;
248 unsigned char buffer[0x20];
249
250 /* issue the command to enable speed changes */
251 result = usb_control_msg(usb_dev_handle_list[portnum], 0x40,
252 MODE_CMD, MOD_SPEED_CHANGE_EN, 0x0001, NULL, 0x0, TIMEOUT_VALUE);
253 //printf("result is %d\n", result);
254
255 /* repeat until the unit is not idle */
256 do {
257 /* get the status */
258 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81,
259 buffer, 0x20, TIMEOUT_VALUE);
260 //printf("result is %d\n", result);
261
262 //for (result = 0; result < 0x20; result++) {
263 // printf("%02X: %02X\n", result, buffer[result]);
264 //}
265 } while (!(buffer[0x08] & 0x20) && !(result < 0));
266
267 /* issue the command to change the speed */
268 result = usb_control_msg(usb_dev_handle_list[portnum], 0x40,
269 MODE_CMD, MOD_1WIRE_SPEED, new_speed ? 0x0002 : 0x0000, NULL, 0x0, TIMEOUT_VALUE);
270 //printf("result is %d\n", result);
271
272 /* repeat until the unit is not idle */
273 do {
274 /* get the status */
275 result = usb_bulk_read(usb_dev_handle_list[portnum], 0x81,
276 buffer, 0x20, TIMEOUT_VALUE);
277 //printf("result is %d\n", result);
278
279 //for (result = 0; result < 0x20; result++) {
280 // printf("%02X: %02X\n", result, buffer[result]);
281 //}
282 } while (!(buffer[0x08] & 0x20) && !(result < 0));
283
284 /* return the data */
285 return new_speed;
286 }
287
288 //--------------------------------------------------------------------------
289 // Set the 1-Wire Net line level. The values for NewLevel are
290 // as follows:
291 //
292 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
293 // indicate the symbolic port number.
294 // 'new_level' - new level defined as
295 // MODE_NORMAL 0x00
296 // MODE_STRONG5 0x02
297 // MODE_PROGRAM 0x04
298 // MODE_BREAK 0x08
299 //
300 // Returns: current 1-Wire Net level
301 //
owLevel(int portnum,SMALLINT new_level)302 int owLevel(int portnum, SMALLINT new_level)
303 {
304 // Adapter supports it but not implemented yet
305 return 0;
306 }
307
308 //--------------------------------------------------------------------------
309 // This procedure creates a fixed 480 microseconds 12 volt pulse
310 // on the 1-Wire Net for programming EPROM iButtons.
311 //
312 // 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
313 // indicate the symbolic port number.
314 //
315 // Returns: TRUE successful
316 // FALSE program voltage not available
317 //
owProgramPulse(int portnum)318 int owProgramPulse(int portnum)
319 {
320 // Adapter supports it but not implemented yet
321 return 0;
322 }
323
324 //--------------------------------------------------------------------------
325 // Description:
326 // Delay for at least 'len' ms
327 //
msDelay(int len)328 void msDelay(int len)
329 {
330 struct timespec s; // Set aside memory space on the stack
331
332 s.tv_sec = len / 1000;
333 s.tv_nsec = (len - (s.tv_sec * 1000)) * 1000000;
334 nanosleep(&s, NULL);
335 }
336
337 //--------------------------------------------------------------------------
338 // Get the current millisecond tick count. Does not have to represent
339 // an actual time, it just needs to be an incrementing timer.
340 //
msGettick(void)341 long msGettick(void)
342 {
343 struct timezone tmzone;
344 struct timeval tmval;
345 long ms;
346
347 gettimeofday(&tmval,&tmzone);
348 ms = (tmval.tv_sec & 0xFFFF) * 1000 + tmval.tv_usec / 1000;
349 return ms;
350 }
351
352 //--------------------------------------------------------------------------
353 // Send 8 bits of communication to the 1-Wire Net and verify that the
354 // 8 bits read from the 1-Wire Net is the same (write operation).
355 // The parameter 'sendbyte' least significant 8 bits are used. After the
356 // 8 bits are sent change the level of the 1-Wire net.
357 //
358 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
359 // OpenCOM to indicate the port number.
360 // 'sendbyte' - 8 bits to send (least significant byte)
361 //
362 // Returns: TRUE: bytes written and echo was the same
363 // FALSE: echo was not the same
364 //
owWriteBytePower(int portnum,SMALLINT sendbyte)365 SMALLINT owWriteBytePower(int portnum, SMALLINT sendbyte)
366 {
367 // replace if platform has better implementation (faster response)
368 if (!hasPowerDelivery(portnum))
369 return FALSE;
370
371 if(owTouchByte(portnum,sendbyte) != sendbyte)
372 return FALSE;
373
374 if(owLevel(portnum,MODE_STRONG5) != MODE_STRONG5)
375 return FALSE;
376
377 return TRUE;
378 }
379
380 //--------------------------------------------------------------------------
381 // Send 1 bit of communication to the 1-Wire Net and verify that the
382 // response matches the 'applyPowerResponse' bit and apply power delivery
383 // to the 1-Wire net. Note that some implementations may apply the power
384 // first and then turn it off if the response is incorrect.
385 //
386 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
387 // OpenCOM to indicate the port number.
388 // 'applyPowerResponse' - 1 bit response to check, if correct then start
389 // power delivery
390 //
391 // Returns: TRUE: bit written and response correct, strong pullup now on
392 // FALSE: response incorrect
393 //
owReadBitPower(int portnum,SMALLINT applyPowerResponse)394 SMALLINT owReadBitPower(int portnum, SMALLINT applyPowerResponse)
395 {
396 // replace if platform has better implementation (faster response)
397 if (!hasPowerDelivery(portnum))
398 return FALSE;
399
400 if(owTouchBit(portnum,0x01) != applyPowerResponse)
401 return FALSE;
402
403 if(owLevel(portnum,MODE_STRONG5) != MODE_STRONG5)
404 return FALSE;
405
406 return TRUE;
407 }
408
409 //--------------------------------------------------------------------------
410 // This procedure indicates wether the adapter can deliver power.
411 //
412 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
413 // OpenCOM to indicate the port number.
414 //
415 // Returns: TRUE if adapter is capable of delivering power.
416 //
hasPowerDelivery(int portnum)417 SMALLINT hasPowerDelivery(int portnum)
418 {
419 // Adapter supports it but not implemented yet
420 return FALSE;
421 }
422
423 //--------------------------------------------------------------------------
424 // This procedure indicates wether the adapter can deliver power.
425 //
426 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
427 // OpenCOM to indicate the port number.
428 //
429 // Returns: TRUE if adapter is capable of over drive.
430 //
hasOverDrive(int portnum)431 SMALLINT hasOverDrive(int portnum)
432 {
433 return TRUE;
434 }
435
436 //--------------------------------------------------------------------------
437 // This procedure creates a fixed 480 microseconds 12 volt pulse
438 // on the 1-Wire Net for programming EPROM iButtons.
439 //
440 // 'portnum' - number 0 to MAX_PORTNUM-1. This number was provided to
441 // OpenCOM to indicate the port number.
442 //
443 // Returns: TRUE program volatage available
444 // FALSE program voltage not available
hasProgramPulse(int portnum)445 SMALLINT hasProgramPulse(int portnum)
446 {
447 // Adapter supports it but not implemented yet
448 return FALSE;
449 }
450