IPC: Difference between revisions

Yuriks (talk | contribs)
m Fix heading levels ("Skip Level 1, it is page name level." https://www.mediawiki.org/wiki/Help:Formatting)
Yuriks (talk | contribs)
Add some usage info for svcReplyAndReceive
Line 240: Line 240:
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
| Same as above except for read-only buffer. Prior(?) to the kernel version which implemented memory-permission checking for PXI buffers, this was unused and hence triggered a kernelpanic.
|}
|}
== SVCs ==
=== svcReplyAndReceive ===
'''Signature:'''
Result ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)
In a single operation, sends a IPC reply and waits for a new request. <code>handles</code> should be a pointer to an array of <code>handleCount</code> handles.<sup>TODO: Are only port/session handles supported?</sup>
<code>replyTarget</code> should contain a handle to the session to send the reply to. (This us usually the session from which we received the previous request.)
If <code>replyTarget</code> is 0, no reply and the call will simply wait for an incoming event.<sup>TODO: It doesn't seem like the 0xFFFF0000 command id mentioned in the above sections is necessary, but needs confirmation.</sup>
Upon returning, <code>index</code> will contain an index into <code>handles</code> specifying which object changed state.
If it's a server port endpoint, it means that there is a new incoming connection on that port which should be accepted using svcAcceptSession.
If it's a server session endpoint it means that we received a request from that session and should process and then reply to it by calling svcReplyAndReceive again with <code>replyTarget</code> set to that session's handle.
An example of a server svcReplyAndReceive loop is:
#define MAX_CLIENTS 4
Handle server_port = ...;
s32 requesting_index;
Handle handles[1 + MAX_CLIENTS] = { server_port };
s32 connected_clients = 0;
Handle reply_target = 0;
while (true) {
    Result res = svcReplyAndReceive(&requesting_index, &handles, 1 + connected_clients, reply_target);
    if (res == 0xC920181A) {
        // Session was closed by remote
        // TODO: Handle disconnects
        reply_target = 0;
        continue;
    }
    if (requesting_index == 0) {
        // New connection in server_port
        ASSERT(connected_client < MAX_CLIENTS);
        svcAcceptSession(&handles[1 + connected_clients++], server_port);
        reply_target = 0;
        continue;
    }
    reply_target = handles[requesting_index];
    // Handle command here and write reply to command buffer
}