From 239e05967d48a94391a463e41f30bc8d33e871db Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 6 Dec 2024 10:32:53 -0800 Subject: [PATCH] . --- packages/runtime/src/$.ts | 2 +- packages/runtime/src/switch/service.ts | 34 +++--- source/service.c | 162 +++++++++++++++++++++---- 3 files changed, 161 insertions(+), 37 deletions(-) diff --git a/packages/runtime/src/$.ts b/packages/runtime/src/$.ts index 5480b8ab..b8922a3f 100644 --- a/packages/runtime/src/$.ts +++ b/packages/runtime/src/$.ts @@ -226,7 +226,7 @@ export interface Init { // service.c serviceInit(c: ClassOf): () => void; - serviceNew(name: string): Service; + serviceNew(name?: string): Service; // software-keyboard.c swkbdCreate(fns: { diff --git a/packages/runtime/src/switch/service.ts b/packages/runtime/src/switch/service.ts index 89881598..7275fda2 100644 --- a/packages/runtime/src/switch/service.ts +++ b/packages/runtime/src/switch/service.ts @@ -3,30 +3,40 @@ import { proto, stub } from '../utils'; export interface ServiceDispatchParams { //Handle target_session; + targetSession?: number; + //u32 context; + context?: number; //SfBufferAttrs buffer_attrs; //SfBuffer buffers[8]; - bufferAttrs: number[]; - buffers: ArrayBuffer[]; + bufferAttrs?: number[]; + buffers?: ArrayBuffer[]; //bool in_send_pid; + inSendPid?: boolean; //u32 in_num_objects; //const Service* in_objects[8]; + inObjects?: Service[]; //u32 in_num_handles; //Handle in_handles[8]; + inHandles?: number[]; //u32 out_num_objects; //Service* out_objects; + // XXX: This seems to always be 1 (hence why its not an array?) + outObjects?: Service[]; //SfOutHandleAttrs out_handle_attrs; //Handle* out_handles; + outHandleAttrs?: number[]; + outHandles?: number[]; } export class Service { - constructor(name: string) { + constructor(name?: string) { return proto($.serviceNew(name), Service); } @@ -38,31 +48,27 @@ export class Service { stub(); } - dispatch(rid: number, dispatchParams?: ServiceDispatchParams) { - return this.dispatchInOut(rid, undefined, undefined, dispatchParams); + dispatch(rid: number, params?: ServiceDispatchParams) { + this.dispatchInOut(rid, undefined, undefined, params); } - dispatchIn( - rid: number, - inData: ArrayBuffer, - dispatchParams?: ServiceDispatchParams, - ) { - return this.dispatchInOut(rid, inData, undefined, dispatchParams); + dispatchIn(rid: number, inData: ArrayBuffer, parmas?: ServiceDispatchParams) { + this.dispatchInOut(rid, inData, undefined, parmas); } dispatchOut( rid: number, outData: ArrayBuffer, - dispatchParams?: ServiceDispatchParams, + params?: ServiceDispatchParams, ) { - return this.dispatchInOut(rid, undefined, outData, dispatchParams); + this.dispatchInOut(rid, undefined, outData, params); } dispatchInOut( rid: number, inData?: ArrayBuffer, outData?: ArrayBuffer, - dispatchParams?: ServiceDispatchParams, + params?: ServiceDispatchParams, ) { stub(); } diff --git a/source/service.c b/source/service.c index fd0459d4..6654dae6 100644 --- a/source/service.c +++ b/source/service.c @@ -22,16 +22,19 @@ static JSValue nx_service_new(JSContext *ctx, JSValueConst this_val, int argc, return JS_EXCEPTION; } - const char *name = JS_ToCString(ctx, argv[0]); - if (!name) { - return JS_EXCEPTION; - } + // If a string is passed in, then it is the name of the service module + if (JS_IsString(argv[0])) { + const char *name = JS_ToCString(ctx, argv[0]); + if (!name) { + return JS_EXCEPTION; + } - Result rc = smGetService(&data->service, name); - JS_FreeCString(ctx, name); + Result rc = smGetService(&data->service, name); + JS_FreeCString(ctx, name); - if (R_FAILED(rc)) { - return nx_throw_libnx_error(ctx, rc, "smGetService()"); + if (R_FAILED(rc)) { + return nx_throw_libnx_error(ctx, rc, "smGetService()"); + } } JSValue obj = JS_NewObjectClass(ctx, nx_service_class_id); @@ -49,6 +52,15 @@ static JSValue nx_service_is_active(JSContext *ctx, JSValueConst this_val, return JS_NewBool(ctx, serviceIsActive(&data->service)); } +static JSValue nx_service_is_domain(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) { + nx_service_t *data = JS_GetOpaque2(ctx, this_val, nx_service_class_id); + if (!data) + return JS_EXCEPTION; + + return JS_NewBool(ctx, serviceIsDomain(&data->service)); +} + static JSValue nx_service_is_override(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { nx_service_t *data = JS_GetOpaque2(ctx, this_val, nx_service_class_id); @@ -83,6 +95,28 @@ static JSValue nx_service_dispatch_in_out(JSContext *ctx, JSValueConst this_val, SfDispatchParams disp = {0}; if (JS_IsObject(argv[3])) { + // disp.target_session + JSValue target_session_val = + JS_GetPropertyStr(ctx, argv[3], "targetSession"); + if (JS_IsNumber(target_session_val)) { + if (JS_ToUint32(ctx, &disp.target_session, target_session_val)) { + JS_FreeValue(ctx, target_session_val); + return JS_EXCEPTION; + } + } + JS_FreeValue(ctx, target_session_val); + + // disp.context + JSValue context_val = JS_GetPropertyStr(ctx, argv[3], "context"); + if (JS_IsNumber(context_val)) { + if (JS_ToUint32(ctx, &disp.context, context_val)) { + JS_FreeValue(ctx, context_val); + return JS_EXCEPTION; + } + } + JS_FreeValue(ctx, context_val); + + // disp.buffer_attrs JSValue buffer_attrs_val = JS_GetPropertyStr(ctx, argv[3], "bufferAttrs"); if (JS_IsArray(ctx, buffer_attrs_val)) { @@ -94,24 +128,38 @@ static JSValue nx_service_dispatch_in_out(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, length_val); return JS_EXCEPTION; } - for (u32 i = 0; i < length; i++) { - JSValue v = JS_GetPropertyUint32(ctx, buffer_attrs_val, i); - if (JS_IsNumber(v)) { - u32 attr; - if (JS_ToUint32(ctx, &attr, v)) { - JS_FreeValue(ctx, buffer_attrs_val); - JS_FreeValue(ctx, length_val); - return JS_EXCEPTION; - } - // TODO: all `attr` props - disp.buffer_attrs.attr0 = attr; - } - JS_FreeValue(ctx, v); - } + u32 attr; + JSValue buffer_attr_val; + +#define GET_BUFFER_ATTR(INDEX) \ + buffer_attr_val = JS_GetPropertyStr(ctx, buffer_attrs_val, #INDEX); \ + if (JS_IsNumber(buffer_attr_val)) { \ + if (JS_ToUint32(ctx, &attr, buffer_attr_val)) { \ + JS_FreeValue(ctx, buffer_attr_val); \ + JS_FreeValue(ctx, buffer_attrs_val); \ + JS_FreeValue(ctx, length_val); \ + return JS_EXCEPTION; \ + } \ + disp.buffer_attrs.attr##INDEX = attr; \ + } \ + JS_FreeValue(ctx, buffer_attr_val); + + GET_BUFFER_ATTR(0); + GET_BUFFER_ATTR(1); + GET_BUFFER_ATTR(2); + GET_BUFFER_ATTR(3); + GET_BUFFER_ATTR(4); + GET_BUFFER_ATTR(5); + GET_BUFFER_ATTR(6); + GET_BUFFER_ATTR(7); + +#undef GET_BUFFER_ATTR + JS_FreeValue(ctx, length_val); } JS_FreeValue(ctx, buffer_attrs_val); + // disp.buffers JSValue buffers_val = JS_GetPropertyStr(ctx, argv[3], "buffers"); if (JS_IsArray(ctx, buffers_val)) { JSValue length_val = JS_GetPropertyStr(ctx, buffers_val, "length"); @@ -131,6 +179,75 @@ static JSValue nx_service_dispatch_in_out(JSContext *ctx, JSValueConst this_val, } } JS_FreeValue(ctx, buffers_val); + + // disp.in_send_pid + JSValue in_send_pid_val = JS_GetPropertyStr(ctx, argv[3], "inSendPid"); + if (JS_IsBool(in_send_pid_val)) { + disp.in_send_pid = JS_ToBool(ctx, in_send_pid_val); + } + JS_FreeValue(ctx, in_send_pid_val); + + // disp.in_num_objects + // disp.in_objects + JSValue in_objects_val = JS_GetPropertyStr(ctx, argv[3], "inObjects"); + if (JS_IsArray(ctx, in_objects_val)) { + JSValue length_val = + JS_GetPropertyStr(ctx, in_objects_val, "length"); + if (JS_ToUint32(ctx, &disp.in_num_objects, length_val)) { + JS_FreeValue(ctx, in_objects_val); + JS_FreeValue(ctx, length_val); + return JS_EXCEPTION; + } + + for (u32 i = 0; i < disp.in_num_objects; i++) { + JSValue v = JS_GetPropertyUint32(ctx, in_objects_val, i); + nx_service_t *v_data = + JS_GetOpaque2(ctx, v, nx_service_class_id); + if (!v_data) { + JS_FreeValue(ctx, v); + JS_FreeValue(ctx, in_objects_val); + JS_FreeValue(ctx, length_val); + return JS_EXCEPTION; + } + disp.in_objects[i] = &v_data->service; + JS_FreeValue(ctx, v); + } + + JS_FreeValue(ctx, length_val); + } + JS_FreeValue(ctx, in_objects_val); + + // disp.out_num_objects + // disp.out_objects + JSValue out_objects_val = JS_GetPropertyStr(ctx, argv[3], "outObjects"); + if (JS_IsArray(ctx, out_objects_val)) { + JSValue length_val = + JS_GetPropertyStr(ctx, out_objects_val, "length"); + if (JS_ToUint32(ctx, &disp.out_num_objects, length_val)) { + JS_FreeValue(ctx, out_objects_val); + JS_FreeValue(ctx, length_val); + return JS_EXCEPTION; + } + + for (u32 i = 0; i < disp.out_num_objects; i++) { + JSValue v = JS_GetPropertyUint32(ctx, out_objects_val, i); + nx_service_t *v_data = + JS_GetOpaque2(ctx, v, nx_service_class_id); + if (!v_data) { + JS_FreeValue(ctx, v); + JS_FreeValue(ctx, out_objects_val); + JS_FreeValue(ctx, length_val); + return JS_EXCEPTION; + } + // XXX: This seems to always be 1 in libnx (hence why its not an + // array?) + disp.out_objects = &v_data->service; + JS_FreeValue(ctx, v); + } + + JS_FreeValue(ctx, length_val); + } + JS_FreeValue(ctx, out_objects_val); } Result rc = serviceDispatchImpl(&data->service, rid, in_data, in_data_size, @@ -147,6 +264,7 @@ static JSValue nx_service_init(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSValue proto = JS_GetPropertyStr(ctx, argv[0], "prototype"); NX_DEF_FUNC(proto, "isActive", nx_service_is_active, 0); + NX_DEF_FUNC(proto, "isDomain", nx_service_is_domain, 0); NX_DEF_FUNC(proto, "isOverride", nx_service_is_override, 0); NX_DEF_FUNC(proto, "dispatchInOut", nx_service_dispatch_in_out, 3); JS_FreeValue(ctx, proto);