1 /*
2 OWFS -- One-Wire filesystem
3 OWHTTPD -- One-Wire Web Server
4 Written 2003 Paul H Alfille
5 email: paul.alfille@gmail.com
6 Released under the GPL
7 See the header file: ow.h for full attribution
8 1wire/iButton system from Dallas Semiconductor
9 */
10
11 #include <config.h>
12 #include "owfs_config.h"
13 #include "ow.h"
14 #include "ow_counters.h"
15 #include "ow_connection.h"
16
17 /* All the rest of the program sees is the DS9907_detect and the entry in iroutines */
18
19 static RESET_TYPE DS9097_reset(const struct parsedname *pn);
20 static RESET_TYPE DS9097_reset_in( struct connection_in * in );
21 static GOOD_OR_BAD DS9097_pre_reset(struct connection_in *in ) ;
22 static void DS9097_post_reset(struct connection_in *in ) ;
23 static GOOD_OR_BAD DS9097_sendback_bits(const BYTE * outbits, BYTE * inbits, const size_t length, const struct parsedname *pn);
24 static void DS9097_setroutines(struct connection_in *in);
25 static GOOD_OR_BAD DS9097_send_and_get(const BYTE * bussend, BYTE * busget, const size_t length, struct connection_in *in);
26
27 #define OneBit 0xFF
28 //#define ZeroBit 0xC0
29 // Should be all zero's when we send 8 bits. digitemp write 0xFF or 0x00
30 #define ZeroBit 0x00
31
32 // at slower speed of course
33 #define RESET_BYTE 0xF0
34
35 /* Device-specific functions */
DS9097_setroutines(struct connection_in * in)36 static void DS9097_setroutines(struct connection_in *in)
37 {
38 in->iroutines.detect = DS9097_detect;
39 in->iroutines.reset = DS9097_reset;
40 in->iroutines.next_both = NO_NEXT_BOTH_ROUTINE;
41 in->iroutines.PowerByte = NO_POWERBYTE_ROUTINE;
42 in->iroutines.ProgramPulse = NO_PROGRAMPULSE_ROUTINE;
43 in->iroutines.sendback_data = NO_SENDBACKDATA_ROUTINE;
44 in->iroutines.sendback_bits = DS9097_sendback_bits;
45 in->iroutines.select = NO_SELECT_ROUTINE;
46 in->iroutines.select_and_sendback = NO_SELECTANDSENDBACK_ROUTINE;
47 in->iroutines.set_config = NO_SET_CONFIG_ROUTINE;
48 in->iroutines.get_config = NO_GET_CONFIG_ROUTINE;
49 in->iroutines.reconnect = NO_RECONNECT_ROUTINE;
50 in->iroutines.close = COM_close;
51 in->iroutines.verify = NO_VERIFY_ROUTINE ;
52 in->iroutines.flags = ADAP_FLAG_default;
53 in->bundling_length = UART_FIFO_SIZE / 10;
54 }
55
56 /* _detect is a bit of a misnomer, no detection is actually done */
57 // no bus locking here (higher up)
DS9097_detect(struct port_in * pin)58 GOOD_OR_BAD DS9097_detect(struct port_in *pin)
59 {
60 struct connection_in * in = pin->first ;
61 /* Set up low-level routines */
62 DS9097_setroutines(in);
63
64 in->Adapter = adapter_DS9097;
65 // in->adapter_name already set, to support HA3 and HA4B
66 pin->busmode = bus_passive; // in case initially tried DS9097U
67
68 /* open the COM port in 9600 Baud */
69 COM_set_standard( in ) ; // standard COM port settings
70 pin->vmin = 1; // minimum chars
71 pin->vtime = 0; // decisec wait
72
73 if (pin->init_data == NULL) {
74 LEVEL_DEFAULT("DS9097 (passive) busmaster requires port name");
75 return gbBAD;
76 }
77 RETURN_BAD_IF_BAD(COM_open(in)) ;
78
79 pin->flow = flow_first; // flow control
80 switch( DS9097_reset_in(in) ) {
81 case BUS_RESET_OK:
82 case BUS_RESET_SHORT:
83 return gbGOOD ;
84 default:
85 break ;
86 }
87 if ( GOOD(serial_powercycle(in)) ) {
88 switch( DS9097_reset_in(in) ) {
89 case BUS_RESET_OK:
90 case BUS_RESET_SHORT:
91 return gbGOOD ;
92 default:
93 break ;
94 }
95 }
96
97 /* open the COM port in 9600 Baud */
98 /* Second pass */
99 pin->flow = flow_second ;
100 RETURN_BAD_IF_BAD(COM_change(in)) ;
101
102 switch( DS9097_reset_in(in) ) {
103 case BUS_RESET_OK:
104 case BUS_RESET_SHORT:
105 return gbGOOD ;
106 default:
107 break ;
108 }
109
110 /* open the COM port in 9600 Baud */
111 /* Third pass, hardware flow control */
112 pin->flow = flow_first ;
113 RETURN_BAD_IF_BAD(COM_change(in)) ;
114
115 switch( DS9097_reset_in(in) ) {
116 case BUS_RESET_OK:
117 case BUS_RESET_SHORT:
118 return gbGOOD ;
119 default:
120 break ;
121 }
122
123 return gbBAD ;
124 }
125
126 /* DS9097 Reset -- A little different from DS2480B */
127 /* Puts in 9600 baud, sends 11110000 then reads response */
DS9097_reset(const struct parsedname * pn)128 static RESET_TYPE DS9097_reset(const struct parsedname *pn)
129 {
130 return DS9097_reset_in( pn->selected_connection ) ;
131 }
132
133 /* DS9097 Reset -- A little different from DS2480B */
134 /* Puts in 9600 baud, sends 11110000 then reads response */
DS9097_reset_in(struct connection_in * in)135 static RESET_TYPE DS9097_reset_in( struct connection_in * in )
136 {
137 BYTE resetbyte = RESET_BYTE;
138 BYTE responsebyte;
139
140 if ( BAD( DS9097_pre_reset( in ) ) ) {
141 return BUS_RESET_ERROR ;
142 }
143
144 if ( BAD( DS9097_send_and_get(&resetbyte, &responsebyte, 1, in )) ) {
145 DS9097_post_reset( in) ;
146 return BUS_RESET_ERROR ;
147 }
148
149 DS9097_post_reset(in) ;
150
151 switch (responsebyte) {
152 case 0x00:
153 return BUS_RESET_SHORT;
154 case RESET_BYTE:
155 // no presence
156 in->AnyDevices = anydevices_no ;
157 return BUS_RESET_OK;
158 default:
159 in->AnyDevices = anydevices_yes ;
160 return BUS_RESET_OK;
161 }
162 }
163
164 /* Puts in 9600 baud */
DS9097_pre_reset(struct connection_in * in)165 static GOOD_OR_BAD DS9097_pre_reset(struct connection_in *in )
166 {
167 struct port_in * pin = in->pown ;
168
169 RETURN_BAD_IF_BAD( COM_test(in) ) ;
170
171 /* 8 data bits */
172 pin->bits = 8 ;
173 pin->baud = B9600 ;
174
175 if ( BAD( COM_change(in)) ) {
176 ERROR_CONNECT("Cannot set attributes: %s", SAFESTRING(DEVICENAME(in)));
177 DS9097_post_reset( in ) ;
178 return gbBAD;
179 }
180 return gbGOOD;
181 }
182
183 /* Restore terminal settings (serial port settings) */
DS9097_post_reset(struct connection_in * in)184 static void DS9097_post_reset(struct connection_in *in )
185 {
186 struct port_in * pin = in->pown ;
187
188 if (Globals.eightbit_serial) {
189 /* coninue with 8 data bits */
190 pin->bits = 8;
191 } else {
192 /* 6 data bits, Receiver enabled, Hangup, Dont change "owner" */
193 pin->bits = 6;
194 }
195 #ifndef B115200
196 /* MacOSX support max 38400 in termios.h ? */
197 pin->baud = B38400 ;
198 #else
199 pin->baud = B115200 ;
200 #endif
201
202 /* Flush the input and output buffers */
203 COM_flush(in); // Adds no appreciable time
204 COM_change(in) ;
205 }
206
207 /* Symmetric */
208 /* send bits -- read bits */
209 /* Actually uses bit zero of each byte */
210 /* So each "byte" has already been expanded to 1 bit/byte */
211 /* Dispatches DS9097_MAX_BITS "bits" at a time */
212 #define DS9097_MAX_BITS 24
DS9097_sendback_bits(const BYTE * outbits,BYTE * inbits,const size_t length,const struct parsedname * pn)213 static GOOD_OR_BAD DS9097_sendback_bits(const BYTE * outbits, BYTE * inbits, const size_t length, const struct parsedname *pn)
214 {
215 BYTE local_data[DS9097_MAX_BITS];
216 size_t global_counter ;
217 size_t local_counter ;
218 size_t offset ;
219 struct connection_in * in = pn->selected_connection ;
220
221 /* Split into smaller packets? */
222 for ( local_counter = global_counter = offset = 0 ; offset < length ; ) {
223 // encode this bit
224 local_data[local_counter] = outbits[global_counter] ? OneBit : ZeroBit;
225 // point to next one
226 ++local_counter ;
227 ++global_counter ;
228 // test if enough bits to send to master
229 if (local_counter == DS9097_MAX_BITS || global_counter == length) {
230 /* Communication with DS9097 routine */
231 /* Up to DS9097_MAX_BITS bits at a time */
232 if ( BAD( DS9097_send_and_get( local_data, &inbits[offset], local_counter, in )) ) {
233 STAT_ADD1_BUS(e_bus_errors, in);
234 return gbBAD;
235 }
236 offset += local_counter ;
237 local_counter = 0 ;
238 }
239 }
240
241 /* Decode Bits */
242 for (global_counter = 0; global_counter < length; ++global_counter) {
243 inbits[global_counter] &= 0x01; // mask out all but lowest bit
244 }
245
246 return gbGOOD;
247 }
248
249 /* Routine to send a string of bits and get another string back */
DS9097_send_and_get(const BYTE * bussend,BYTE * busget,const size_t length,struct connection_in * in)250 static GOOD_OR_BAD DS9097_send_and_get(const BYTE * bussend, BYTE * busget, const size_t length, struct connection_in * in)
251 {
252 switch( in->pown->type ) {
253 case ct_telnet:
254 RETURN_BAD_IF_BAD( telnet_write_binary( bussend, length, in) ) ;
255 break ;
256 case ct_serial:
257 default:
258 RETURN_BAD_IF_BAD( COM_write( bussend, length, in ) ) ;
259 break ;
260 }
261
262 /* get back string -- with timeout and partial read loop */
263 return COM_read( busget, length, in ) ;
264 }
265