/* * Copyright (c) 2010-2013 Douglas Gilbert. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /***************************************************************** * w1_bbtest.c * * One wire "bit-banging" test program. Uses bidirectional GPIO line on * the FoxLX/G20 to manipulate the one wire IO line. For The FoxLX on the * G port only IOG0 and IOG24 are suitable. The IO line should have a * pull-up resistor on it (try 4.7k). This utility runs the master end * of one wire protocol in the user space. This code follows the Linux * convention as uses "w1" as an abbreviation for "one wire". * * Based on Arduino OneWire library logic * * Note that the one wire protocol does not like being interrupted by * the OS scheduler as often happens to a user space program like this. * So getting CRC errors from time to time is expected. Note that the * I2C protocol is much more robust in this respect. * * Alternative: Instead of using this bit banging user space program * then the Linux kernel w1_gpio module could be used together with * a w1 "slaves" driver. For the one wire temperature chips: DS18B20, * DS18C20 and DS1822; the additional module is called w1_therm . * You will need to find which GPIO line it uses (I used PB16 on the * FoxG20). If a w1 slave is found then: * # cat '/sys/devices/w1 bus master/w1_master_slaves' * will return the device id. Then use that device id like this: * # cat '/sys/devices/w1 bus master/28-0000018a43ea/w1_slave' * 3e 01 4b 46 7f ff 02 10 6c : crc=6c YES * 3e 01 4b 46 7f ff 02 10 6c t=19875 * The temperature*16 is in the first 2 bytes, LSB,MSB * 318/16 = 19.875 C [0x13e=318] * ****************************************************/ /************************************************************** * Linux seems to have a pass-through interface for w1 based * on the netlink mechanism. In the kernel source see: * Documentation/w1/w1.netlink **************************************************************/ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include #include static const char * version_str = "1.08 20130604"; #define SEARCH_TRIES 7 struct w1_search_obj_t { int junction; int exhausted; unsigned char addr[8]; }; static int w1_response_len = 0; static int verbose = 0; static const char * summary = "One wire bit banging test program. If there is only one slave on the " "bus\na reset followed by ROM READ (0x33) should read the slave's " "64 bit ROM code:\n'w1_bbtest -b -i 33 -r 8'. To read a temperature " "from a DS18B20, first start\nthe conversion with " "'w1_bbtest -b -i cc,44' (SKIP ROM, START CONVERSION) then\n" "read the scratchpad with 'w1_bbtest -b -i cc,be -r 9 -c'. The CRC " "should\nbe 0 and the temperature is in the first two bytes " "returned.\n" "For parasitic mode on a DS18B20 add '-f' to the start the conversion " "command.\n"; #ifdef __CRIS__ #include #define GPIO_PORTA PORTA #define GPIO_PORTB PORTB #define GPIO_PORTG PORTG /* A one wire device (slave) can work in parasitic mode in which it "bleeds" * power from the IO line from the master. In that case it needs only two * wires (i.e. ground and IO). For the time being we will assume three wires * (i.e. ground, +5 volts and IO). We believe this should work with the * ETRAX 100LX chip for the same reasons given in the corresponding section * of i2c_bbtest.c (i.e. the I2C bit banging test program). * * Timings are quite precise in one wire so there is a danger bit banging * on a GPIO line from the user space. If this process gets swapped out * by the kernel scheduler while talking to the one wire slave then that * transaction will fail. The expectation is an error will be caught at * a higher level (e.g. bad CRC or timeout) and the operation will be * retried. */ /* FoxLX IOG0 (J7.22), another candidate would be IOG24 (J7.21) */ #define DEF_W1_IO_LINE 0 #define DEF_W1_IO_PORT GPIO_PORTG /* Value of 100 seems to give about 5 microseconds delay. Want clock low * for about 5 us and then up for 5 us for 100 KHz clock rate. */ // #define DELAY_LOOP_COUNT 100 static int w1_io_mask = (1 << DEF_W1_IO_LINE); static int w1_io_port = DEF_W1_IO_PORT; static void usage(void) { fprintf(stderr, "Usage: " "w1_bbtest [-b] [-c] [-d ] [-D ] [-f] [-h] " "[-i ]\n" " [-r ] [-R] [-s] [-v] [-V] [-z]\n" " where:\n" " -b bus reset\n" " -c calculate CRC on number read. If CRC is 0 " "then\n" " exit status 0, else exit status is 1\n" " -d IO port bit number (def: %d)\n" " -D IO port ('a', 'b' or 'g' (def: 'g')\n" " -f force DQ high for 750 milliseconds after " "command\n" " -h print usage message\n" " -i send this string to device where 'H' is an " "ASCII hex\n" " byte.\n" " -r number of bytes to request from slave (def: " "0)\n" " -R read a single bit from the slave\n" " -s search bus for slaves, print their ROM values\n" " -v increase verbosity (multiple times for more)\n" " -V print version string then exit\n" " -z attempt to drive DQ line low for 20 seconds\n\n" "%s", DEF_W1_IO_LINE, summary); } /* On the LX, each call to rand() in the loop takes about * 1.375 microseconds */ static int w1_delay_us(int microseconds, int plus_io) { int k, num; int n = 0; if (plus_io) microseconds -= 2; if (microseconds <= 0) return 0; else { num = (microseconds * 8) / 11; for (k = 0; k < num; ++k) n += rand(); } return n; } // Get the IO line state static int w1_getbit(void) { return gpiogetbits(w1_io_port, w1_io_mask) ? 1 : 0; } // Set the IO line as output static void w1_dir_out(void) { gpiosetdir(w1_io_port, DIROUT, w1_io_mask); } // Set the IO line as input static void w1_dir_in(void) { gpiosetdir(w1_io_port, DIRIN, w1_io_mask); } // Does setup direction, assumes direction is set out static void w1_setbit(int state) { if (state) gpiosetbits(w1_io_port, w1_io_mask); else gpioclearbits(w1_io_port, w1_io_mask); } // Set the IO line state (and direction). Use tristate pullup on // input direction for "high". static void w1_data(int state) { if (1 == state) // let pull-up resistor do the work w1_dir_in(); else { w1_dir_out(); gpioclearbits(w1_io_port, w1_io_mask); } } #elif defined(__ARM_EABI__) #define EXPORT_FILE "/sys/class/gpio/export" #define UNEXPORT_FILE "/sys/class/gpio/unexport" #define GPIO_BASE_FILE "/sys/class/gpio/gpio" #define PIO_BASE_FILE "/sys/class/gpio/pio" #define GPIO_BANK_ORIGIN "/sys/class/gpio/gpiochip0" /* Earlier kernels (G20+G25) offset GPIO numbers by 32 so * /sys/class/gpio/gpiochip32 (a directory) was the lowest numbered bank * and corresponded to PIOA (therefore PA0 was gpio number 32). By lk 3.7 * /sys/class/gpio/gpiochip0 existed and corresponded to PIOA (therefore * PA0 becomes gpio number 0). * In lk 3.8 the sysfs gpio file names changed from /sys/class/gpio/gpio37 * to /sys/class/gpio/pioB5 however the export and unexport files still * expect GPIO numbers. */ /* PB0 (J7.9) */ #define DEF_W1_PIN 82 /* either PC18 or PB18 */ static int w1_pin = DEF_W1_PIN; static int w1_port = 'B'; /* bank (i.e. 'A', 'B', etc ). */ static int w1_pin_in_bank = (DEF_W1_PIN % 32); static int exp_w1 = -1; static int unexp_w1 = -1; static int direction_w1 = -1; static int val_w1 = -1; static int origin0 = 0; static void usage(void) { fprintf(stderr, "Usage: " "w1_bbtest [-b] [-c] [-f] [-h] [-i ] [-p ] " "[-r ]\n" " [-R] [-s] [-t] [-v] [-V] [-z]\n" " where:\n" " -b bus reset\n" " -c calculate CRC on number read, report\n" " -f force DQ high for 750 milliseconds after " "command\n" " -h print usage message\n" " -i send this string to device where 'H' is an " "ASCII hex\n" " byte.\n" " -p gpio pin number to use (def: %d)\n" " -r number of bytes to request from slave (def: " "0)\n" " -R read a single bit from the slave\n" " -s search bus for slaves, print their ROM values\n" " -v increase verbosity (multiple times for more)\n" " -V print version string then exit\n" " -z attempt to drive both SCL and SDA lines low " "(testing)\n\n" "%s", DEF_W1_PIN, summary); } /* On the g20, each call to rand() in the loop takes about * 0.40 microseconds */ static int w1_delay_us(int microseconds, int plus_io) { int k, num; int n = 0; if (plus_io) microseconds -= 2; /* approximate one IO operation overhead */ if (microseconds <= 0) return 0; else if (microseconds >= 200) { struct timespec ts; ts.tv_sec = microseconds / 1000000; ts.tv_nsec = (microseconds % 1000000) * 1000; nanosleep(&ts, NULL); /* assume won't be interrupted */ } else { num = (microseconds * 5) / 2; for (k = 0; k < num; ++k) n += rand(); } return n; } static int w1_getbit(void) { char b[2]; int res; memset(b, 0, sizeof(b)); if ((res = pread(val_w1, b, 1, 0)) <= 0) { if (verbose > 2) { if (0 == res) fprintf(stderr, "%s: pread returns 0\n", __FUNCTION__ ); else fprintf(stderr, "%s: pread err: %s\n", __FUNCTION__ , strerror(errno)); } return 1; } return ('0' != b[0]); } static void w1_dir_out(void) { pwrite(direction_w1, "out", 3, 0); } static void w1_dir_in(void) { pwrite(direction_w1, "in", 2, 0); } static void w1_setbit(int state) { if (state) pwrite(direction_w1, "high", 4, 0); else pwrite(direction_w1, "low", 3, 0); } static void w1_data(int state) { if (state) pwrite(direction_w1, "in", 2, 0); else pwrite(direction_w1, "low", 3, 0); } // Return -1 for problems, 0 for okay static int init_atmel_pin() { struct stat sb; char b[256]; char base_dir[128]; exp_w1 = open(EXPORT_FILE, O_WRONLY); if (exp_w1 < 0) { fprintf(stderr, "Open %s: %s\n", EXPORT_FILE, strerror(errno)); return -1; } unexp_w1 = open(UNEXPORT_FILE, O_WRONLY); if (unexp_w1 < 0) { fprintf(stderr, "Open %s: %s\n", UNEXPORT_FILE, strerror(errno)); return -1; } snprintf(b, sizeof(b), "%d", w1_pin); if (pwrite(exp_w1, b, strlen(b), 0) < 0) { fprintf(stderr, "Unable to export W1 [pin %d] (already in use?): " "%s\n", w1_pin, strerror(errno)); return -1; } /* check if /sys/class/gpio/gpio directory exists */ snprintf(base_dir, sizeof(base_dir), "%s%d", GPIO_BASE_FILE, w1_pin); if (stat(base_dir, &sb) >= 0) { if (verbose > 1) fprintf(stderr, "%s found so continue in original manner\n", base_dir); } else { if (verbose > 2) fprintf(stderr, "%s not found, now check for pinctrl " "convention\n", base_dir); /* check if /sys/class/gpio/pio directory exists */ snprintf(base_dir, sizeof(base_dir), "%s%c%d", PIO_BASE_FILE, w1_port, w1_pin_in_bank); if (stat(base_dir, &sb) >= 0) { if (verbose > 1) fprintf(stderr, "%s found so pinctrl convention\n", base_dir); } else { fprintf(stderr, "Unable to find sysfs directory %s (for " "direction)\n", base_dir); return -1; } } snprintf(b, sizeof(b), "%s/direction", base_dir); direction_w1 = open(b, O_RDWR); if (direction_w1 < 0) { fprintf(stderr, "Open %s: %s\n", b, strerror(errno)); return -1; } snprintf(b, sizeof(b), "%s/value", base_dir); val_w1 = open(b, O_RDWR); if (val_w1 < 0) { fprintf(stderr, "Open %s: %s\n", b, strerror(errno)); return -1; } return 0; } static void cleanup_atmel_pins(void) { char b[256]; if (val_w1 >= 0) close(val_w1); if (direction_w1 >= 0) close(direction_w1); if (unexp_w1 >= 0) { if (w1_pin >= 0) { snprintf(b, sizeof(b), "%d", w1_pin); if (pwrite(unexp_w1, b, strlen(b), 0) < 0) fprintf(stderr, "Unable to unexport W1: %s\n", strerror(errno)); } close(unexp_w1); } if (exp_w1 >= 0) close(exp_w1); } #else // Dummies if no hardware #define GPIO_PORTA 'A' #define GPIO_PORTB 'B' #define GPIO_PORTG 'G' #define DEF_W1_PIN 64 static int w1_pin = DEF_W1_PIN; static void usage(void) { fprintf(stderr, "Usage: " "w1_bbtest [-b] [-f] [-h] [-i ] [-p ] [-r ]\n" " [-R] [-s] [-t] [-v] [-V] [-z]\n" " where:\n" " -b bus reset\n" " -f force DQ high for 750 milliseconds after " "command\n" " -h print usage message\n" " -i send this string to device where 'H' is an " "ASCII hex\n" " byte.\n" " -p gpio pin number to use (def: %d)\n" " -r number of bytes to request from slave (def: " "0)\n" " -R read a single bit from the slave\n" " -s search bus for slaves, print their ROM values\n" " -v increase verbosity (multiple times for more)\n" " -V print version string then exit\n" " -z attempt to drive both SCL and SDA lines low " "(testing)\n\n" "One wire bit banging test program. Dummy, no hardware\n", DEF_W1_PIN); } static int w1_delay_us(int microseconds, int plus_io) { microseconds = plus_io; /* dummy, to suppress warning */ return 0; } static int w1_getbit(void) { return 1; } static void w1_dir_out(void) { } static void w1_dir_in(void) { } static void w1_setbit(int state) { } static void w1_data(int state) { } #endif /* Should wait 250 us for bus to come high, if not return 1. * If so, do reset sequence and return 1 if there is a "presence" * pulse, else return 0. */ static int w1_reset(void) { int res; int retries = 125; w1_dir_in(); do { if (0 == retries--) return 0; w1_delay_us(2, 0); } while (! w1_getbit()); w1_data(0); w1_delay_us(500, 1); w1_dir_in(); w1_delay_us(65, 1); res = ! w1_getbit(); w1_delay_us(490, 1); return res; } static int low_time[2] = {55, 5}; static int high_time[2] = {5, 55}; static void w1_write_bit(int v) { v = !!v; w1_data(0); w1_delay_us(low_time[v], 1); #if 1 w1_dir_in(); #else w1_setbit(1); #endif w1_delay_us(high_time[v], 1); } static int w1_read_bit(void) { int res; w1_data(0); w1_delay_us(1, 0); w1_dir_in(); w1_delay_us(5, 1); res = w1_getbit(); w1_delay_us(60, 0); return res; } static void w1_write(unsigned char b, int power) { int mask, k; for (k = 0, mask=0x1; k < 8; ++k, mask <<= 1) w1_write_bit(!!(mask & b)); if (0 == power) { w1_dir_in(); // w1_setbit(0); // ?? } } static unsigned char w1_read(void) { unsigned char res = 0; int mask, k; for (k = 0, mask=0x1; k < 8; ++k, mask <<= 1) { if (w1_read_bit()) res |= mask; } return res; } // 'romp' assumed to point to an array of 8 bytes which is the // rom_id of the device to select. static void w1_select(unsigned char * romp) { int k; w1_write(0x55, 0); for (k = 0; k < 8; ++k) w1_write(romp[k], 0); } static void w1_skip(void) { w1_write(0xcc, 0); } static void w1_depower(void) { w1_dir_in(); } static void clear_search_object(struct w1_search_obj_t * wsp) { wsp->junction = -1; wsp->exhausted = 0; memset(wsp->addr, 0, sizeof(wsp->addr)); } /* * Returns 1 for got something, 0 for exhausted, -1 for reset failure * and -2 for bad bits (try again ?). */ static int w1_search(struct w1_search_obj_t * wsp, unsigned char * new_addrp) { int k; int lastJunction = -1; int done = 1; unsigned char a, nota, kbyte, kmask; if (wsp->exhausted) { if (verbose > 1) fprintf(stderr, "%s: exhausted exit\n", __FUNCTION__ ); return 0; } if (! w1_reset()) { if (verbose) fprintf(stderr, "%s: reset failed\n", __FUNCTION__ ); return -1; } w1_write(0xf0, 0); for (k = 0; k < 64; ++k) { a = w1_read_bit(); nota = w1_read_bit(); kbyte = k / 8; kmask = 1 << (k & 0x7); if (a && nota) { if (verbose) fprintf(stderr, "%s: a && nota both set, k =%d\n", __FUNCTION__ , k); return -2; } if (! (a || nota)) { if (k == wsp->junction) { a = 1; wsp->junction = lastJunction; } else if (k < wsp->junction) { if (wsp->addr[kbyte] & kmask) a = 1; else { a = 0; done = 0; lastJunction = k; } } else { a = 0; wsp->junction = k; done = 0; } lastJunction = k; } if (a) wsp->addr[kbyte] |= kmask; else wsp->addr[kbyte] &= ~kmask; w1_write_bit(a); } if (done) wsp->exhausted = 1; if (new_addrp) memcpy(new_addrp, wsp->addr, 8); return 1; } static unsigned char w1_crc8(const unsigned char * ucp, int len) { int k, j; unsigned char b, m, res; for (k = 0, res = 0; k < len; ++k) { b = ucp[k]; for (j = 0; j < 8; ++j) { m = (res ^ b) & 0x1; res >>= 1; if (m) res ^= 0x8c; b >>= 1; } } return res; } /* Read comma (or single space) separated ASCII hex bytes from 'inp' into * 'arr'. Number written placed in *arr_len. If first char in 'inp' is "-" * reads from stdin instead. With stdin whitespace may be a separator and * lines starting with "#" ignored. Returns 0 is successful, else 1 . */ static int read_hex(const char * inp, unsigned char * arr, int max_arr_len, int * arr_len) { int in_len, k, j, m, off; unsigned int h; const char * lcp; const char * cp; const char * c2p; char line[512]; if ((NULL == inp) || (NULL == arr) || (NULL == arr_len)) return 1; lcp = inp; in_len = strlen(inp); if (0 == in_len) { *arr_len = 0; } if ('-' == inp[0]) { /* read from stdin */ for (j = 0, off = 0; j < 512; ++j) { if (NULL == fgets(line, sizeof(line), stdin)) break; in_len = strlen(line); if (in_len > 0) { if ('\n' == line[in_len - 1]) { --in_len; line[in_len] = '\0'; } } if (0 == in_len) continue; lcp = line; m = strspn(lcp, " \t"); if (m == in_len) continue; lcp += m; in_len -= m; if ('#' == *lcp) continue; k = strspn(lcp, "0123456789aAbBcCdDeEfF ,\t"); if (in_len != k) { fprintf(stderr, "read_hex: syntax error at " "line %d, pos %d\n", j + 1, m + k + 1); return 1; } for (k = 0; k < 1024; ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { fprintf(stderr, "read_hex: hex number " "larger than 0xff in line %d, pos %d\n", j + 1, (int)(lcp - line + 1)); return 1; } if ((off + k) >= max_arr_len) { fprintf(stderr, "read_hex: array length exceeded\n"); return 1; } arr[off + k] = h; lcp = strpbrk(lcp, " ,\t"); if (NULL == lcp) break; lcp += strspn(lcp, " ,\t"); if ('\0' == *lcp) break; } else { fprintf(stderr, "read_hex: error in " "line %d, at pos %d\n", j + 1, (int)(lcp - line + 1)); return 1; } } off += k + 1; } *arr_len = off; } else { /* hex string on command line */ k = strspn(inp, "0123456789aAbBcCdDeEfF, "); if (in_len != k) { fprintf(stderr, "read_hex: error at pos %d\n", k + 1); return 1; } for (k = 0; k < max_arr_len; ++k) { if (1 == sscanf(lcp, "%x", &h)) { if (h > 0xff) { fprintf(stderr, "read_hex: hex number larger " "than 0xff at pos %d\n", (int)(lcp - inp + 1)); return 1; } arr[k] = h; cp = strchr(lcp, ','); c2p = strchr(lcp, ' '); if (NULL == cp) cp = c2p; if (NULL == cp) break; if (c2p && (c2p < cp)) cp = c2p; lcp = cp + 1; } else { fprintf(stderr, "read_hex: error at pos %d\n", (int)(lcp - inp + 1)); return 1; } } *arr_len = k + 1; if (k >= max_arr_len) { fprintf(stderr, "read_hex: array length exceeded\n"); return 1; } } return 0; } int main(int argc, char ** argv) { int ch, opt, k, j; unsigned char command[1024]; int bus_reset = 0; int do_force = 0; int do_search = 0; int cmd_len = 0; int check_crc = 0; int read_1bit = 0; int zero_test = 0; int ret = 1; struct w1_search_obj_t w1so; unsigned char rom_id[8]; #ifdef __CRIS__ const char * optstr = "bcd:D:fhi:r:RsvVz"; #else const char * optstr = "bcfhi:p:r:RsvVz"; #endif #ifdef __ARM_EABI__ struct stat sb; #endif unsigned char arr[1024]; memset(arr, 0, sizeof(arr)); while ((opt = getopt(argc, argv, optstr)) != -1) { switch (opt) { case 'b': ++bus_reset; break; case 'c': ++check_crc; break; #ifdef __CRIS__ case 'd': k = atoi(optarg); if ((k < 0) || (k > 31)) { fprintf(stderr, "'-d' expects a bit number from 0 to 31\n"); exit(EXIT_FAILURE); } w1_io_mask = (1 << k); break; case 'D': ch = toupper(*optarg); if ('A' == ch) w1_io_port = GPIO_PORTA; else if ('B' == ch) w1_io_port = GPIO_PORTB; else if ('G' == ch) w1_io_port = GPIO_PORTG; else { fprintf(stderr, "'-D' expects 'A', 'B' or 'G'\n"); exit(EXIT_FAILURE); } break; #endif case 'f': ++do_force; break; case 'h': usage(); exit(EXIT_SUCCESS); case 'i': if (read_hex(optarg, command, sizeof(command), &cmd_len)) { fprintf(stderr, "failed reading arguments to '-i'\n"); exit(EXIT_FAILURE); } break; #ifndef __CRIS__ case 'p': k = atoi(optarg); if ((k < 0) || (k > 159)) { fprintf(stderr, "'-p' expects a pin number from 0 to 159\n"); exit(EXIT_FAILURE); } w1_pin = k; break; #endif case 'r': k = atoi(optarg); if ((k < 0) || (k > 512)) { fprintf(stderr, "'-r' expects a length from 0 to 512\n"); exit(EXIT_FAILURE); } w1_response_len = k; break; case 'R': ++read_1bit; break; case 's': ++do_search; break; case 'v': ++verbose; break; case 'V': printf("%s\n", version_str); exit(EXIT_SUCCESS); case 'z': ++zero_test; break; default: /* '?' */ usage(); exit(EXIT_FAILURE); } } if (optind < argc) { if (optind < argc) { for (; optind < argc; ++optind) fprintf(stderr, "Unexpected extra argument: %s\n", argv[optind]); usage(); exit(EXIT_FAILURE); } } #ifdef __ARM_EABI__ if (stat(GPIO_BANK_ORIGIN, &sb) >= 0) { if (verbose > 1) fprintf(stderr, "%s found so kernel pin numbers start at 0 " "(for PA0)\n", GPIO_BANK_ORIGIN); origin0 = 1; } else if (verbose > 2) fprintf(stderr, "%s not found so kernel pin numbers start at 32 " "(for PA0)\n", GPIO_BANK_ORIGIN); if (w1_pin < 0) w1_pin = ((w1_port - 'A' + (! origin0)) * 32) + w1_pin_in_bank; else { w1_port = (w1_pin / 32) + (! origin0) + 'A'; w1_pin_in_bank = (w1_pin % 32); printf("Note: gpio P%c%d is being used for w1\n", w1_port, w1_pin_in_bank); } if (init_atmel_pin() < 0) goto the_end; #endif if (bus_reset) { k = w1_reset(); fprintf(stderr, "After the bus reset, a 'presence' pulse pulse " "is %sdetected\n", (k ? "" : "NOT ")); } if (do_search) { for (k = 0, ch = 0; k < SEARCH_TRIES; ++k) { clear_search_object(&w1so); for (j = 0; (ch = w1_search(&w1so, rom_id)) > 0; ++j) { fprintf(stderr, "One wire device ROM ID: "); for (k = 0; k < 8; ++k) fprintf(stderr, " %02x", rom_id[k]); fprintf(stderr, "\n"); if (w1_crc8(rom_id, 7) != rom_id[7]) fprintf(stderr, " CRC(8) invalid\n"); } if (j > 0) break; if (ch >= -1) break; /* So if we got -2 (bad bits) try again */ if (k >= 3) sleep(1); } if (0 == j) fprintf(stderr, "No one wire devices found\n"); ret = 0; goto the_end; } if (zero_test) { fprintf(stderr, "drive DQ line low, wait 20 seconds " "then tristate it and exit\n"); w1_data(0); sleep(20); w1_dir_in(); ret = 0; goto the_end; } if (0 == cmd_len) { if (read_1bit) goto read1bit; if (! bus_reset) { fprintf(stderr, "In the absence of '-b', '-s', '-R' or '-z' " "expect '-i'\n"); usage(); } goto the_end; } if (verbose > 2) fprintf(stderr, "read_hex read %d bytes from '-i' arguments\n", cmd_len); for (k = 0; k < cmd_len; ++k) w1_write(command[k], 0); if (read_1bit) { read1bit: k = w1_getbit(); if (verbose) fprintf(stderr, "after command read %s bit\n", k ? "high" : "low"); else fprintf(stderr, "%d\n", k); ret = 0; goto the_end; } else if (w1_response_len > 0) { if (verbose > 2) fprintf(stderr, "Received these bytes from slave:\n"); for (k = 0; k < w1_response_len; ++k) arr[k] = w1_read(); for (k = 0; k < w1_response_len; ++k) { if ((k > 0) && (0 == (k % 16))) printf("\n"); printf(" %02x", arr[k]); } printf("\n"); if (check_crc) { k = w1_crc8(arr, w1_response_len); printf(" CRC.8 calculation on result yields 0x%x\n", k); ret = !! k; } else ret = 0; } else ret = 0; if (do_force) { struct timespec delay_req; w1_setbit(1); delay_req.tv_sec = 0; delay_req.tv_nsec = 750000000; /* 750 milliseconds */ nanosleep(&delay_req, NULL); w1_depower(); } the_end: #ifdef __ARM_EABI__ cleanup_atmel_pins(); #endif return ret; }