diff mbox series

[4/4] qmi: Enable basic client creation if it is not subclassed

Message ID 20240228215319.153068-4-steve.schrock@getcruise.com (mailing list archive)
State Superseded
Headers show
Series [1/4] qmi: Create a method to find a service by type | expand

Commit Message

Steve Schrock Feb. 28, 2024, 9:53 p.m. UTC
QRTR does not require client ID allocation requests.
---
 drivers/qmimodem/qmi.c | 93 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 76 insertions(+), 17 deletions(-)
diff mbox series

Patch

diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c
index afa7b962..6e4c99dc 100644
--- a/drivers/qmimodem/qmi.c
+++ b/drivers/qmimodem/qmi.c
@@ -1388,6 +1388,25 @@  static uint8_t __ctl_request_submit(struct qmi_device_qmux *qmux,
 	return req->tid;
 }
 
+static struct qmi_service *service_create(struct qmi_device *device,
+			const struct qmi_service_info *info, uint8_t client_id)
+{
+	struct qmi_service *service = l_new(struct qmi_service, 1);
+
+	service->ref_count = 1;
+	service->device = device;
+	service->client_id = client_id;
+	service->notify_list = l_queue_new();
+
+	memcpy(&service->info, info, sizeof(service->info));
+
+	__debug_device(device, "service created [client=%d,type=%d]",
+					service->client_id,
+					service->info.service_type);
+
+	return service;
+}
+
 static void service_create_shared_reply(struct l_idle *idle, void *user_data)
 {
 	struct service_create_shared_data *data = user_data;
@@ -1398,6 +1417,20 @@  static void service_create_shared_reply(struct l_idle *idle, void *user_data)
 	DISCOVERY_DONE(data, data->service, data->user_data);
 }
 
+static void service_create_shared_no_discovery_reply(struct l_idle *idle,
+								void *user_data)
+{
+	struct service_create_shared_data *data = user_data;
+
+	l_idle_remove(data->idle);
+	data->idle = NULL;
+
+	if (data->func)
+		data->func(data->service, data->user_data);
+
+	__discovery_free(&data->super);
+}
+
 static void service_create_shared_pending_reply(struct qmi_device *device,
 						unsigned int type,
 						struct qmi_service *service)
@@ -1664,6 +1697,7 @@  static void qmux_client_create_callback(uint16_t message, uint16_t length,
 	struct qmi_device *device = data->device;
 	struct qmi_service *service = NULL;
 	struct qmi_service *old_service = NULL;
+	struct qmi_service_info info;
 	const struct qmi_result_code *result_code;
 	const struct qmi_client_id *client_id;
 	uint16_t len;
@@ -1686,21 +1720,12 @@  static void qmux_client_create_callback(uint16_t message, uint16_t length,
 	if (client_id->service != data->type)
 		goto done;
 
-	service = l_new(struct qmi_service, 1);
-
-	service->ref_count = 1;
-	service->device = data->device;
+	memset(&info, 0, sizeof(service->info));
+	info.service_type = data->type;
+	info.major = data->major;
+	info.minor = data->minor;
 
-	service->info.service_type = data->type;
-	service->info.major = data->major;
-	service->info.minor = data->minor;
-
-	service->client_id = client_id->client;
-	service->notify_list = l_queue_new();
-
-	__debug_device(device, "service created [client=%d,type=%d]",
-					service->client_id,
-					service->info.service_type);
+	service = service_create(device, &info, client_id->client);
 
 	hash_id = service_list_create_hash(service->info.service_type,
 							service->client_id);
@@ -2443,6 +2468,43 @@  bool qmi_service_create_shared(struct qmi_device *device, uint16_t type,
 	if (type == QMI_SERVICE_CONTROL)
 		return false;
 
+	if (!device->ops->client_create) {
+		struct service_create_shared_data *data;
+
+		/*
+		 * The hash id is simply the service type in this case. There
+		 * is no "pending" state for discovery and no client id.
+		 */
+		service = l_hashmap_lookup(device->service_list,
+						L_UINT_TO_PTR(type_val));
+		if (!service) {
+			const struct qmi_service_info *info;
+
+			info = __find_service_info_by_type(device, type);
+			if (!info)
+				return false;
+
+			service = service_create(device, info, 0);
+			l_hashmap_insert(device->service_list,
+					L_UINT_TO_PTR(type_val), service);
+		}
+
+		data = l_new(struct service_create_shared_data, 1);
+
+		data->super.destroy = service_create_shared_data_free;
+		data->device = device;
+		data->func = func;
+		data->user_data = user_data;
+		data->destroy = destroy;
+
+		data->service = qmi_service_ref(service);
+		data->idle = l_idle_create(
+				service_create_shared_no_discovery_reply,
+				data, NULL);
+
+		return true;
+	}
+
 	shared = l_hashmap_lookup(device->service_list,
 					L_UINT_TO_PTR(type_val | 0x80000000));
 
@@ -2486,9 +2548,6 @@  bool qmi_service_create_shared(struct qmi_device *device, uint16_t type,
 		return true;
 	}
 
-	if (!device->ops->client_create)
-		return -ENOTSUP;
-
 	r = device->ops->client_create(device, type, func, user_data, destroy);
 	return r == 0;
 }