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 |
| + | } |