staticint w1_timeout = 10;
module_param_named(timeout, w1_timeout, int, 0);
MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
staticint w1_timeout_us;
module_param_named(timeout_us, w1_timeout_us, int, 0);
MODULE_PARM_DESC(timeout_us, "time in microseconds between automatic slave searches");
/* A search stops when w1_max_slave_count devices have been found in that * search. The next search will start over and detect the same set of devices * on a static 1-wire bus. Memory is not allocated based on this number, just * on the number of devices known to the kernel. Having a high number does not * consume additional resources. As a special case, if there is only one * device on the network and w1_max_slave_count is set to 1, the device id can * be read directly skipping the normal slower search process.
*/ int w1_max_slave_count = 64;
module_param_named(max_slave_count, w1_max_slave_count, int, 0);
MODULE_PARM_DESC(max_slave_count, "maximum number of slaves detected in a search");
int w1_max_slave_ttl = 10;
module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
MODULE_PARM_DESC(slave_ttl, "Number of searches not seeing a slave before it will be removed");
mutex_lock(&md->mutex);
md->search_count = tmp;
mutex_unlock(&md->mutex); /* Only wake if it is going to be searching. */ if (tmp)
wake_up_process(md->thread);
if (kstrtoint(buf, 0, &tmp) || tmp < 1) return -EINVAL;
mutex_lock(&md->mutex);
md->max_slave_count = tmp; /* allow each time the max_slave_count is updated */
clear_bit(W1_WARN_MAX_COUNT, &md->flags);
mutex_unlock(&md->mutex);
/* The CRC value isn't read from the user because the sysfs directory * doesn't include it and most messages from the bus search don't * print it either. It would be unreasonable for the user to then * provide it.
*/ constchar *error_msg = "bad slave string format, expecting " "ff-dddddddddddd\n";
if (buf[2] != '-') {
dev_err(dev, "%s", error_msg); return -EINVAL;
}
i = sscanf(buf, "%02x-%012llx", &family, &id); if (i != 2) {
dev_err(dev, "%s", error_msg); return -EINVAL;
}
rn->family = family;
rn->id = id;
if (w1_atoreg_num(dev, buf, count, &rn)) return -EINVAL;
mutex_lock(&md->mutex);
sl = w1_slave_search_device(md, &rn); /* It would be nice to do a targeted search one the one-wire bus * for the new device to see if it is out there or not. But the * current search doesn't support that.
*/ if (sl) {
dev_info(dev, "Device %s already exists\n", sl->name);
result = -EINVAL;
} else {
w1_attach_slave_device(md, &rn);
}
mutex_unlock(&md->mutex);
return result;
}
static ssize_t w1_master_attribute_show_remove(struct device *dev, struct device_attribute *attr, char *buf)
{ int c = PAGE_SIZE;
c -= snprintf(buf+PAGE_SIZE - c, c, "write device id xx-xxxxxxxxxxxx to remove slave\n"); return PAGE_SIZE - c;
}
if (w1_atoreg_num(dev, buf, count, &rn)) return -EINVAL;
mutex_lock(&md->mutex);
sl = w1_slave_search_device(md, &rn); if (sl) {
result = w1_slave_detach(sl); /* refcnt 0 means it was detached in the call */ if (result == 0)
result = count;
} else {
dev_info(dev, "Device %02x-%012llx doesn't exist\n", rn.family,
(unsignedlonglong)rn.id);
result = -EINVAL;
}
mutex_unlock(&md->mutex);
/* slave modules need to be loaded in a context with unlocked mutex */
mutex_unlock(&dev->mutex);
request_module("w1-family-0x%02X", rn->family);
mutex_lock(&dev->mutex);
spin_lock(&w1_flock);
f = w1_family_registered(rn->family); if (!f) {
f= &w1_default_family;
dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
rn->family, rn->family,
(unsignedlonglong)rn->id, rn->crc);
}
__w1_family_get(f);
spin_unlock(&w1_flock);
int w1_slave_detach(struct w1_slave *sl)
{ /* Only detach a slave once as it decreases the refcnt each time. */ int destroy_now;
mutex_lock(&sl->master->list_mutex);
destroy_now = !test_bit(W1_SLAVE_DETACH, &sl->flags);
set_bit(W1_SLAVE_DETACH, &sl->flags);
mutex_unlock(&sl->master->list_mutex);
mutex_lock(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
dev_dbg(&dev->dev, "Reconnecting slaves in device %s " "for family %02x.\n", dev->name, f->fid);
mutex_lock(&dev->mutex);
mutex_lock(&dev->list_mutex);
list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) { /* If it is a new family, slaves with the default * family driver and are that family will be * connected. If the family is going away, devices * matching that family are reconneced.
*/ if ((attach && sl->family->fid == W1_FAMILY_DEFAULT
&& sl->reg_num.family == f->fid) ||
(!attach && sl->family->fid == f->fid)) { struct w1_reg_num rn;
mutex_unlock(&dev->list_mutex);
memcpy(&rn, &sl->reg_num, sizeof(rn)); /* If it was already in use let the automatic * scan pick it up again later.
*/ if (!w1_slave_detach(sl))
w1_attach_slave_device(dev, &rn);
mutex_lock(&dev->list_mutex);
}
}
dev_dbg(&dev->dev, "Reconnecting slaves in device %s " "has been finished.\n", dev->name);
mutex_unlock(&dev->list_mutex);
mutex_unlock(&dev->mutex);
}
mutex_unlock(&w1_mlock);
}
/* quirk: * DS28E04 (1w eeprom) has strapping pins to change * address, but will not update the crc. So normal rules * for consistent w1 addresses are violated. We test * with the 7 LSBs of the address forced high. * * (char*)&rn_le = { family, addr_lsb, ..., addr_msb, crc }.
*/ if (crc != tmp->crc && tmp->family == W1_FAMILY_DS28E04) {
u64 corr_le = rn_le;
sl = w1_slave_search_device(dev, tmp); if (sl) {
set_bit(W1_SLAVE_ACTIVE, &sl->flags);
} else { if (rn && w1_addr_crc_is_valid(dev, rn))
w1_attach_slave_device(dev, tmp);
}
atomic_dec(&dev->refcnt);
}
/** * w1_search() - Performs a ROM Search & registers any devices found. * @dev: The master device to search * @search_type: W1_SEARCH to search all devices, or W1_ALARM_SEARCH * to return only devices in the alarmed state * @cb: Function to call when a device is found * * The 1-wire search is a simple binary tree search. * For each bit of the address, we read two bits and write one bit. * The bit written will put to sleep all devies that don't match that bit. * When the two reads differ, the direction choice is obvious. * When both bits are 0, we must choose a path to take. * When we can scan all 64 bits without having to choose a path, we are done. * * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com *
*/ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
{
u64 last_rn, rn, tmp64; int i, slave_count = 0; int last_zero, last_device; int search_bit, desc_bit;
u8 triplet_ret = 0;
/* * Reset bus and all 1-wire device state machines * so they can respond to our requests. * * Return 0 - device(s) present, 1 - no devices present.
*/
mutex_lock(&dev->bus_mutex); if (w1_reset_bus(dev)) {
mutex_unlock(&dev->bus_mutex);
dev_dbg(&dev->dev, "No devices present on the wire.\n"); break;
}
/* Do fast search on single slave bus */ if (dev->max_slave_count == 1) { int rv;
w1_write_8(dev, W1_READ_ROM);
rv = w1_read_block(dev, (u8 *)&rn, 8);
mutex_unlock(&dev->bus_mutex);
if (rv == 8 && rn)
cb(dev, rn);
break;
}
/* Start the search */
w1_write_8(dev, search_type); for (i = 0; i < 64; ++i) { /* Determine the direction/search bit */ if (i == desc_bit)
search_bit = 1; /* took the 0 path last time, so take the 1 path */ elseif (i > desc_bit)
search_bit = 0; /* take the 0 path on the next branch */ else
search_bit = ((last_rn >> i) & 0x1);
/* Read two bits and write one bit */
triplet_ret = w1_triplet(dev, search_bit);
/* quit if no device responded */ if ( (triplet_ret & 0x03) == 0x03 ) break;
/* If both directions were valid, and we took the 0 path... */ if (triplet_ret == 0)
last_zero = i;
/* extract the direction taken & update the device number */
tmp64 = (triplet_ret >> 2);
rn |= (tmp64 << i);
if (!last_device && slave_count == dev->max_slave_count &&
!test_bit(W1_WARN_MAX_COUNT, &dev->flags)) { /* Only max_slave_count will be scanned in a search, * but it will start where it left off next search * until all ids are identified and then it will start * over. A continued search will report the previous * last id as the first id (provided it is still on the * bus).
*/
dev_info(&dev->dev, "%s: max_slave_count %d reached, " "will continue next search.\n", __func__,
dev->max_slave_count);
set_bit(W1_WARN_MAX_COUNT, &dev->flags);
}
}
}
/** * w1_process_callbacks() - execute each dev->async_list callback entry * @dev: w1_master device * * The w1 master list_mutex must be held. * * Return: 1 if there were commands to executed 0 otherwise
*/ int w1_process_callbacks(struct w1_master *dev)
{ int ret = 0; struct w1_async_cmd *async_cmd, *async_n;
/* The list can be added to in another thread, loop until it is empty */ while (!list_empty(&dev->async_list)) {
list_for_each_entry_safe(async_cmd, async_n, &dev->async_list,
async_entry) { /* drop the lock, if it is a search it can take a long
* time */
mutex_unlock(&dev->list_mutex);
async_cmd->cb(dev, async_cmd);
ret = 1;
mutex_lock(&dev->list_mutex);
}
} return ret;
}
int w1_process(void *data)
{ struct w1_master *dev = (struct w1_master *) data; /* As long as w1_timeout is only set by a module parameter the sleep * time can be calculated in jiffies once.
*/ constunsignedlong jtime =
usecs_to_jiffies(w1_timeout * 1000000 + w1_timeout_us); /* remainder if it woke up early */ unsignedlong jremain = 0;
atomic_inc(&dev->refcnt);
for (;;) {
if (!jremain && dev->search_count) {
mutex_lock(&dev->mutex);
w1_search_process(dev, W1_SEARCH);
mutex_unlock(&dev->mutex);
}
mutex_lock(&dev->list_mutex); /* Note, w1_process_callback drops the lock while processing, * but locks it again before returning.
*/ if (!w1_process_callbacks(dev) && jremain) { /* a wake up is either to stop the thread, process * callbacks, or search, it isn't process callbacks, so * schedule a search.
*/
jremain = 1;
}
__set_current_state(TASK_INTERRUPTIBLE);
/* hold list_mutex until after interruptible to prevent loosing * the wakeup signal when async_cmd is added.
*/
mutex_unlock(&dev->list_mutex);
if (kthread_should_stop()) {
__set_current_state(TASK_RUNNING); break;
}
/* Only sleep when the search is active. */ if (dev->search_count) { if (!jremain)
jremain = jtime;
jremain = schedule_timeout(jremain);
} else
schedule();
}
atomic_dec(&dev->refcnt);
return 0;
}
staticint __init w1_init(void)
{ int retval;
pr_info("Driver for 1-wire Dallas network protocol.\n");
w1_init_netlink();
retval = bus_register(&w1_bus_type); if (retval) {
pr_err("Failed to register bus. err=%d.\n", retval); goto err_out_exit_init;
}
retval = driver_register(&w1_master_driver); if (retval) {
pr_err("Failed to register master driver. err=%d.\n",
retval); goto err_out_bus_unregister;
}
retval = driver_register(&w1_slave_driver); if (retval) {
pr_err("Failed to register slave driver. err=%d.\n",
retval); goto err_out_master_unregister;
}
return 0;
#if 0 /* For undoing the slave register if there was a step after it. */
err_out_slave_unregister:
driver_unregister(&w1_slave_driver); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.