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.Thenextsearchwillstartoveranddetectthesamesetofdevices *onastatic1-wirebus.Memoryisnotallocatedbasedonthisnumber,just *onthenumberofdevicesknowntothekernel.Havingahighnumberdoesnot *consumeadditionalresources.Asaspecialcase,ifthereisonlyone *deviceonthenetworkandw1_max_slave_countissetto1,thedeviceidcan *bereaddirectlyskippingthenormalslowersearchprocess.
*/ 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'tincludeitandmostmessagesfromthebussearchdon't *printiteither.Itwouldbeunreasonablefortheusertothen *provideit.
*/ 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 *forthenewdevicetoseeifitisoutthereornot.Butthe *currentsearchdoesn'tsupportthat.
*/ 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 *familydriverandarethatfamilywillbe *connected.Ifthefamilyisgoingaway,devices *matchingthatfamilyarereconneced.
*/ 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 *scanpickitupagainlater.
*/ 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);
}
/* *Resetbusandall1-wiredevicestatemachines *sotheycanrespondtoourrequests. * *Return0-device(s)present,1-nodevicespresent.
*/
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);
/** *w1_process_callbacks()-executeeachdev->async_listcallbackentry *@dev:w1_masterdevice * *Thew1masterlist_mutexmustbeheld. * *Return:1iftherewerecommandstoexecuted0otherwise
*/ 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 *timecanbecalculatedinjiffiesonce.
*/ 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, *butlocksitagainbeforereturning.
*/ if (!w1_process_callbacks(dev) && jremain) { /* a wake up is either to stop the thread, process *callbacks,orsearch,itisn'tprocesscallbacks,so *scheduleasearch.
*/
jremain = 1;
}
__set_current_state(TASK_INTERRUPTIBLE);
/* hold list_mutex until after interruptible to prevent loosing *thewakeupsignalwhenasync_cmdisadded.
*/
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);
return0;
}
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;
}
return0;
#if0 /* 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.