staticint adb_scan_bus(void)
{ int i, highFree=0, noMovement; int devmask = 0; struct adb_request req;
/* assumes adb_handler[] is all zeroes at this point */ for (i = 1; i < 16; i++) { /* see if there is anything at address i */
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(i << 4) | 0xf); if (req.reply_len > 1) /* one or more devices at this address */
adb_handler[i].original_address = i; elseif (i > highFree)
highFree = i;
}
/* Note we reset noMovement to 0 each time we move a device */ for (noMovement = 1; noMovement < 2 && highFree > 0; noMovement++) { for (i = 1; i < 16; i++) { if (adb_handler[i].original_address == 0) continue; /* *Senda"talkregister3"commandtoaddressi *toprovokeacollisionifthereismorethan *onedeviceatthisaddress.
*/
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(i << 4) | 0xf); /* *Movethedevice(s)whichdidn'tdetecta *collisiontoaddress`highFree'.Hopefully *thisonlymovesonedevice.
*/
adb_request(&req, NULL, ADBREQ_SYNC, 3,
(i<< 4) | 0xb, (highFree | 0x60), 0xfe); /* *Seeifanybodyactuallymoved.Thisissuggested *byHWTechNote01: * *https://developer.apple.com/technotes/hw/hw_01.html
*/
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(highFree << 4) | 0xf); if (req.reply_len <= 1) continue; /* *Testwhetherthereareanydevice(s)left *ataddressi.
*/
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(i << 4) | 0xf); if (req.reply_len > 1) { /* *Therearestilloneormoredevices *leftataddressi.Registertheone(s) *wemovedto`highFree',andfindanew *valueforhighFree.
*/
adb_handler[highFree].original_address =
adb_handler[i].original_address; while (highFree > 0 &&
adb_handler[highFree].original_address)
highFree--; if (highFree <= 0) break;
/* Now fill in the handler_id field of the adb_handler entries. */ for (i = 1; i < 16; i++) { if (adb_handler[i].original_address == 0) continue;
adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
(i << 4) | 0xf);
adb_handler[i].handler_id = req.reply[2];
printk(KERN_DEBUG "adb device [%d]: %d 0x%X\n", i,
adb_handler[i].original_address,
adb_handler[i].handler_id);
devmask |= 1 << i;
} return devmask;
}
#ifdef CONFIG_PM /* *notifyclientsbeforesleep
*/ staticint __adb_suspend(struct platform_device *dev, pm_message_t state)
{
adb_got_sleep = 1; /* We need to get a lock on the probe thread */
down(&adb_probe_mutex); /* Stop autopoll */ if (adb_controller->autopoll)
adb_controller->autopoll(0);
blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
int
adb_request(struct adb_request *req, void (*done)(struct adb_request *), int flags, int nbytes, ...)
{
va_list list; int i; int rc; struct completion comp;
if ((adb_controller == NULL) || (adb_controller->send_request == NULL)) return -ENXIO; if (nbytes < 1) return -EINVAL;
req->nbytes = nbytes+1;
req->done = done;
req->reply_expected = flags & ADBREQ_REPLY;
req->data[0] = ADB_PACKET;
va_start(list, nbytes); for (i = 0; i < nbytes; ++i)
req->data[i+1] = va_arg(list, int);
va_end(list);
if (flags & ADBREQ_NOSEND) return0;
/* Synchronous requests block using an on-stack completion */ if (flags & ADBREQ_SYNC) {
WARN_ON(done);
req->done = adb_sync_req_done;
req->arg = ∁
init_completion(&comp);
}
rc = adb_controller->send_request(req, 0);
if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
wait_for_completion(&comp);
return rc;
}
EXPORT_SYMBOL(adb_request);
/* Ultimately this should return the number of devices with thegivendefaultid. Anditdoesitnow!Note:changedbehaviour:Thisfunction willnowregisterifdefault_id_and_handler_idbothmatch buthandler_idcanbeleftto0tomatchwithdefault_idonly. Whenhandler_idisset,thisfunctionwilltrytoadjust
the handler_id id it doesn't match. */ int
adb_register(int default_id, int handler_id, struct adb_ids *ids, void (*handler)(unsignedchar *, int, int))
{ int i;
mutex_lock(&adb_handler_mutex);
ids->nids = 0; for (i = 1; i < 16; i++) { if ((adb_handler[i].original_address == default_id) &&
(!handler_id || (handler_id == adb_handler[i].handler_id) ||
try_handler_change(i, handler_id))) { if (adb_handler[i].handler) {
pr_err("Two handlers for ADB device %d\n",
default_id); continue;
}
write_lock_irq(&adb_handler_lock);
adb_handler[i].handler = handler;
write_unlock_irq(&adb_handler_lock);
ids->id[ids->nids++] = i;
}
}
mutex_unlock(&adb_handler_mutex); return ids->nids;
}
EXPORT_SYMBOL(adb_register);
int
adb_unregister(int index)
{ int ret = -ENODEV;
ret = -EFAULT; if (copy_from_user(req->data, buf, count)) goto out;
atomic_inc(&state->n_pending);
/* If a probe is in progress or we are sleeping, wait for it to complete */
down(&adb_probe_mutex);
/* Queries are special requests sent to the ADB driver itself */ if (req->data[0] == ADB_QUERY) { if (count > 1)
ret = do_adb_query(req); else
ret = -EINVAL;
up(&adb_probe_mutex);
} /* Special case for ADB_BUSRESET request, all others are sent to
the controller */ elseif ((req->data[0] == ADB_PACKET) && (count > 1)
&& (req->data[1] == ADB_BUSRESET)) {
ret = do_adb_reset_bus();
up(&adb_probe_mutex);
atomic_dec(&state->n_pending); if (ret == 0)
ret = count; goto out;
} else {
req->reply_expected = ((req->data[1] & 0xc) == 0xc); if (adb_controller && adb_controller->send_request)
ret = adb_controller->send_request(req, 0); else
ret = -ENXIO;
up(&adb_probe_mutex);
}
staticvoid __init
adbdev_init(void)
{ if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
pr_err("adb: unable to get major %d\n", ADB_MAJOR); return;
}
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.