1、orb_advertise_multi ,一个驱动对应多个实例。适用于驱动相似的多个传感器驱动。
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority) { int result, fd; orb_advert_t advertiser; /* open the node as an advertiser */ fd = node_open(PUBSUB, meta, data, true, instance, priority); if (fd == ERROR) return ERROR; /* get the advertiser handle and close the node */ result = ioctl(fd, ORBIOCGADVERTISER, (unsigned long)&advertiser); close(fd); if (result == ERROR) return ERROR; /* the advertiser must perform an initial publish to initialise the object */ result = orb_publish(meta, advertiser, data); if (result == ERROR) return ERROR; return advertiser; }
--------------------》
int node_open(Flavor f, const struct orb_metadata *meta, const void *data, bool advertiser, int *instance = nullptr, int priority = ORB_PRIO_DEFAULT) { char path[orb_maxpath]; int fd, ret; /* * If meta is null, the object was not defined, i.e. it is not * known to the system. We can't advertise/subscribe such a thing. */ if (nullptr == meta) { errno = ENOENT; return ERROR; } /* * Advertiser must publish an initial value. */ if (advertiser && (data == nullptr)) { errno = EINVAL; return ERROR; } /* * Generate the path to the node and try to open it. */ ret = node_mkpath(path, f, meta, instance); if (ret != OK) { errno = -ret; return ERROR; } /* open the path as either the advertiser or the subscriber */ fd = open(path, (advertiser) ? O_WRONLY : O_RDONLY); /* if we want to advertise and the node existed, we have to re-try again */ if ((fd >= 0) && (instance != nullptr) && (advertiser)) { /* close the fd, we want a new one */ close(fd); /* the node_advertise call will automatically go for the next free entry */ fd = -1; } /* we may need to advertise the node... */ if (fd < 0) { /* try to create the node */ ret = node_advertise(meta, instance, priority); if (ret == OK) { /* update the path, as it might have been updated during the node_advertise call */ ret = node_mkpath(path, f, meta, instance); if (ret != OK) { errno = -ret; return ERROR; } } /* on success, try the open again */ if (ret == OK) { fd = open(path, (advertiser) ? O_WRONLY : O_RDONLY); } } if (fd < 0) { errno = EIO; return ERROR; } /* everything has been OK, we can return the handle now */ return fd; }
------------------------------------------------------->
int node_advertise(const struct orb_metadata *meta, int *instance = nullptr, int priority = ORB_PRIO_DEFAULT) { int fd = -1; int ret = ERROR; /* fill advertiser data */ const struct orb_advertdata adv = { meta, instance, priority }; /* open the control device */ fd = open(TOPIC_MASTER_DEVICE_PATH, 0); if (fd < 0) goto out; /* advertise the object */ ret = ioctl(fd, ORBIOCADVERTISE, (unsigned long)(uintptr_t)&adv); /* it's OK if it already exists */ if ((OK != ret) && (EEXIST == errno)) { ret = OK; } out: if (fd >= 0) close(fd); return ret; }
------------------------------------------------------------->
int ORBDevMaster::ioctl(struct file *filp, int cmd, unsigned long arg) { int ret; switch (cmd) { case ORBIOCADVERTISE: { const struct orb_advertdata *adv = (const struct orb_advertdata *)arg; const struct orb_metadata *meta = adv->meta; const char *objname; const char *devpath; char nodepath[orb_maxpath]; ORBDevNode *node; /* set instance to zero - we could allow selective multi-pubs later based on value */ if (adv->instance != nullptr) { *(adv->instance) = 0; //注意在这里轻质把instance变量转化为0 } /* construct a path to the node - this also checks the node name */ ret = node_mkpath(nodepath, _flavor, meta, adv->instance); if (ret != OK) { return ret; } /* ensure that only one advertiser runs through this critical section */ lock(); ret = ERROR; /* try for topic groups */ const unsigned max_group_tries = (adv->instance != nullptr) ? ORB_MULTI_MAX_INSTANCES : 1; unsigned group_tries = 0; do { /* if path is modifyable change try index */ if (adv->instance != nullptr) { /* replace the number at the end of the string */ nodepath[strlen(nodepath) - 1] = '0' + group_tries; *(adv->instance) = group_tries; } /* driver wants a permanent copy of the node name, so make one here */ objname = strdup(meta->o_name); if (objname == nullptr) { return -ENOMEM; } /* driver wants a permanent copy of the path, so make one here */ devpath = strdup(nodepath); if (devpath == nullptr) { return -ENOMEM; } /* construct the new node */ node = new ORBDevNode(meta, objname, devpath, adv->priority); /* if we didn't get a device, that's bad */ if (node == nullptr) { unlock(); return -ENOMEM; } /* initialise the node - this may fail if e.g. a node with this name already exists */ ret = node->init(); /* if init failed, discard the node and its name */ if (ret != OK) { delete node; free((void *)objname); free((void *)devpath); } group_tries++; } while (ret != OK && (group_tries < max_group_tries)); if (group_tries > max_group_tries) { ret = -ENOMEM; } /* the file handle for the driver has been created, unlock */ unlock(); return ret; } default: /* give it to the superclass */ return CDev::ioctl(filp, cmd, arg); } }
蓝色字体中的红色字体是关键,可以看到已经存在的实例会报错。