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