Compare commits
	
		
			122 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7725869a27 | ||
| 
						 | 
					7b33c6d70b | ||
| 
						 | 
					b38ddeb4c0 | ||
| 
						 | 
					db387d213a | ||
| 
						 | 
					ae0af8512f | ||
| 
						 | 
					bf51970422 | ||
| 
						 | 
					e11e9a7eb1 | ||
| 
						 | 
					606801a3c3 | ||
| 
						 | 
					881dd6eef9 | ||
| 
						 | 
					66ed8a3c7d | ||
| 
						 | 
					89f3f5886f | ||
| 
						 | 
					499e48df9a | ||
| 
						 | 
					ad536645e7 | ||
| 
						 | 
					0281a5ccdc | ||
| 
						 | 
					ce70fb9744 | ||
| 
						 | 
					4e0723ca6c | ||
| 
						 | 
					050f83a22b | ||
| 
						 | 
					736032efa0 | ||
| 
						 | 
					c6d8e8d1e6 | ||
| 
						 | 
					ee7fdd06d4 | ||
| 
						 | 
					8fa78cc777 | ||
| 
						 | 
					f4276f8602 | ||
| 
						 | 
					ff1195ffc6 | ||
| 
						 | 
					11673897fa | ||
| 
						 | 
					520fe4257a | ||
| 
						 | 
					179e8d6160 | ||
| 
						 | 
					6d52c79f6c | ||
| 
						 | 
					48026e4fe6 | ||
| 
						 | 
					451711a1ce | ||
| 
						 | 
					32523f2b1a | ||
| 
						 | 
					e0e475c4e3 | ||
| 
						 | 
					02789fa6a4 | ||
| 
						 | 
					6a4f434592 | ||
| 
						 | 
					a96fdf6c42 | ||
| 
						 | 
					77a9b126ef | ||
| 
						 | 
					5085ccc3c6 | ||
| 
						 | 
					4eb1ced700 | ||
| 
						 | 
					68ff7696d7 | ||
| 
						 | 
					b6021807dd | ||
| 
						 | 
					ea6071fb11 | ||
| 
						 | 
					b50d08ddd9 | ||
| 
						 | 
					2f4b216758 | ||
| 
						 | 
					0af836aa7a | ||
| 
						 | 
					d2227efa9e | ||
| 
						 | 
					092bc3aa5f | ||
| 
						 | 
					f52b5e98d6 | ||
| 
						 | 
					d81a883289 | ||
| 
						 | 
					a1de914f94 | ||
| 
						 | 
					b1e7cb78d2 | ||
| 
						 | 
					309383a3dd | ||
| 
						 | 
					24a5e281d7 | ||
| 
						 | 
					6a9a0b7d5e | ||
| 
						 | 
					4b95a7efef | ||
| 
						 | 
					1d14925196 | ||
| 
						 | 
					77d600150a | ||
| 
						 | 
					7684a717de | ||
| 
						 | 
					6be4596f0d | ||
| 
						 | 
					76f7fa6ee1 | ||
| 
						 | 
					c3135de5c7 | ||
| 
						 | 
					4595539656 | ||
| 
						 | 
					62a0764577 | ||
| 
						 | 
					ff65e170e1 | ||
| 
						 | 
					0ce5f268c9 | ||
| 
						 | 
					ab379e4fe3 | ||
| 
						 | 
					e4ab7078a1 | ||
| 
						 | 
					9b1c2df489 | ||
| 
						 | 
					62212c5165 | ||
| 
						 | 
					ea502d417a | ||
| 
						 | 
					1ce4ff615b | ||
| 
						 | 
					72b3fc58ec | ||
| 
						 | 
					4140def1fc | ||
| 
						 | 
					901396b385 | ||
| 
						 | 
					052a0e11fb | ||
| 
						 | 
					024f319164 | ||
| 
						 | 
					91f7b80459 | ||
| 
						 | 
					13076eb3ec | ||
| 
						 | 
					27695ee5ff | ||
| 
						 | 
					7b5656d2a8 | ||
| 
						 | 
					788d472839 | ||
| 
						 | 
					7f4446b3fd | ||
| 
						 | 
					e08ef1bdae | ||
| 
						 | 
					8039bfe66e | ||
| 
						 | 
					7e23a74fbf | ||
| 
						 | 
					a9463baaaf | ||
| 
						 | 
					ddee97fc93 | ||
| 
						 | 
					f562149d18 | ||
| 
						 | 
					21d659a5c5 | ||
| 
						 | 
					71f5632e2d | ||
| 
						 | 
					30e7563d94 | ||
| 
						 | 
					26a321bc36 | ||
| 
						 | 
					f141bd1615 | ||
| 
						 | 
					d3a63909c7 | ||
| 
						 | 
					aaa1c0c9a0 | ||
| 
						 | 
					e0ffc4d60c | ||
| 
						 | 
					94d469380e | ||
| 
						 | 
					7e4b839fc6 | ||
| 
						 | 
					0708177e94 | ||
| 
						 | 
					9047ef9a56 | ||
| 
						 | 
					bb61f00d57 | ||
| 
						 | 
					601ef084ee | ||
| 
						 | 
					3cd41646b4 | ||
| 
						 | 
					d1fb490f9b | ||
| 
						 | 
					7e0c222f1d | ||
| 
						 | 
					f5b2cc062c | ||
| 
						 | 
					9e246ebb55 | ||
| 
						 | 
					5f5afc3d76 | ||
| 
						 | 
					eab404c46b | ||
| 
						 | 
					395a50ba3d | ||
| 
						 | 
					79379ea3d1 | ||
| 
						 | 
					197e84e71a | ||
| 
						 | 
					30ea57a3cb | ||
| 
						 | 
					49fcc2a599 | ||
| 
						 | 
					6d9f87f7ea | ||
| 
						 | 
					efc30cd06d | ||
| 
						 | 
					6959979384 | ||
| 
						 | 
					1ebf32bc73 | ||
| 
						 | 
					a119a68374 | ||
| 
						 | 
					1e7506e7ac | ||
| 
						 | 
					bd20f5aabe | ||
| 
						 | 
					42fc35fbc7 | ||
| 
						 | 
					031228b3a8 | ||
| 
						 | 
					bcb1963582 | 
							
								
								
									
										12
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,15 +1,15 @@
 | 
			
		||||
*~
 | 
			
		||||
debian/files
 | 
			
		||||
debian/libgbinder-radio-dev.debhelper.log
 | 
			
		||||
debian/libgbinder-radio-dev.substvars
 | 
			
		||||
debian/libgbinder-radio-dev
 | 
			
		||||
debian/libgbinder-radio.debhelper.log
 | 
			
		||||
debian/libgbinder-radio.postinst.debhelper
 | 
			
		||||
debian/libgbinder-radio.postrm.debhelper
 | 
			
		||||
debian/libgbinder-radio.substvars
 | 
			
		||||
debian/libgbinder-radio
 | 
			
		||||
debian/*.debhelper.log
 | 
			
		||||
debian/*.debhelper
 | 
			
		||||
debian/*.substvars
 | 
			
		||||
debian/*.install
 | 
			
		||||
debian/tmp
 | 
			
		||||
documentation.list
 | 
			
		||||
unit/coverage/*.gcov
 | 
			
		||||
unit/coverage/report
 | 
			
		||||
installroot
 | 
			
		||||
build
 | 
			
		||||
RPMS
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								AUTHORS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
Danct12 <danct12@disroot.org>
 | 
			
		||||
Denis Grigorev <d.grigorev@omprussia.ru>
 | 
			
		||||
Frajo Haider <f_haider@gmx.at>
 | 
			
		||||
Matti Lehtimäki <matti.lehtimaki@jolla.com>
 | 
			
		||||
Rinigus <rinigus.git@gmail.com>
 | 
			
		||||
Slava Monich <slava@monich.com>
 | 
			
		||||
							
								
								
									
										33
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 | 
			
		||||
You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright
 | 
			
		||||
     notice, this list of conditions and the following disclaimer.
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
     documentation and/or other materials provided with the distribution.
 | 
			
		||||
  3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
     contributors may be used to endorse or promote products derived
 | 
			
		||||
     from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
The views and conclusions contained in the software and documentation
 | 
			
		||||
are those of the authors and should not be interpreted as representing
 | 
			
		||||
any official policies, either expressed or implied.
 | 
			
		||||
							
								
								
									
										56
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,7 +1,8 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: clean all debug release coverage
 | 
			
		||||
.PHONY: clean all debug release coverage test
 | 
			
		||||
.PHONY: debug_lib release_lib coverage_lib
 | 
			
		||||
.PHONY: print_debug_lib print_release_lib print_coverage_lib
 | 
			
		||||
.PHONY: pkgconfig install install-dev
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -22,8 +23,8 @@ all: debug release pkgconfig
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
VERSION_MAJOR = 1
 | 
			
		||||
VERSION_MINOR = 0
 | 
			
		||||
VERSION_RELEASE = 0
 | 
			
		||||
VERSION_MINOR = 5
 | 
			
		||||
VERSION_RELEASE = 3
 | 
			
		||||
 | 
			
		||||
# Version for pkg-config
 | 
			
		||||
PCVERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_RELEASE)
 | 
			
		||||
@@ -46,8 +47,13 @@ LIB = $(LIB_NAME).a
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC = \
 | 
			
		||||
  radio_base.c \
 | 
			
		||||
  radio_client.c \
 | 
			
		||||
  radio_config.c \
 | 
			
		||||
  radio_instance.c \
 | 
			
		||||
  radio_registry.c \
 | 
			
		||||
  radio_request.c \
 | 
			
		||||
  radio_request_group.c \
 | 
			
		||||
  radio_util.c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
@@ -78,10 +84,7 @@ DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
COVERAGE_FLAGS = -g
 | 
			
		||||
 | 
			
		||||
ifndef KEEP_SYMBOLS
 | 
			
		||||
KEEP_SYMBOLS = 0
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
KEEP_SYMBOLS ?= 0
 | 
			
		||||
ifneq ($(KEEP_SYMBOLS),0)
 | 
			
		||||
RELEASE_FLAGS += -g
 | 
			
		||||
endif
 | 
			
		||||
@@ -141,12 +144,26 @@ coverage_lib: $(COVERAGE_LIB)
 | 
			
		||||
 | 
			
		||||
pkgconfig: $(PKGCONFIG)
 | 
			
		||||
 | 
			
		||||
print_debug_lib:
 | 
			
		||||
	@echo $(DEBUG_LIB)
 | 
			
		||||
 | 
			
		||||
print_release_lib:
 | 
			
		||||
	@echo $(RELEASE_LIB)
 | 
			
		||||
 | 
			
		||||
print_coverage_lib:
 | 
			
		||||
	@echo $(COVERAGE_LIB)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	make -C unit clean
 | 
			
		||||
	rm -f *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~
 | 
			
		||||
	rm -fr $(BUILD_DIR) RPMS installroot
 | 
			
		||||
	rm -fr debian/tmp debian/libgbinder debian/libgbinder-dev
 | 
			
		||||
	rm -fr debian/tmp debian/libgbinder-radio debian/libgbinder-radio-dev
 | 
			
		||||
	rm -f documentation.list debian/files debian/*.substvars
 | 
			
		||||
	rm -f debian/*.debhelper.log debian/*.debhelper debian/*~
 | 
			
		||||
	rm -f debian/*.install
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
	make -C unit test
 | 
			
		||||
 | 
			
		||||
$(BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
@@ -192,25 +209,34 @@ $(COVERAGE_LIB): $(COVERAGE_OBJS)
 | 
			
		||||
	$(AR) rc $@ $?
 | 
			
		||||
	ranlib $@
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# LIBDIR usually gets substituted with arch specific dir.
 | 
			
		||||
# It's relative in deb build and can be whatever in rpm build.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
LIBDIR ?= usr/lib
 | 
			
		||||
ABS_LIBDIR := $(shell echo /$(LIBDIR) | sed -r 's|/+|/|g')
 | 
			
		||||
 | 
			
		||||
$(PKGCONFIG): $(LIB_NAME).pc.in Makefile
 | 
			
		||||
	sed -e 's/\[version\]/'$(PCVERSION)/g $< > $@
 | 
			
		||||
	sed -e 's|@version@|$(PCVERSION)|g' -e 's|@libdir@|$(ABS_LIBDIR)|g' $< > $@
 | 
			
		||||
 | 
			
		||||
debian/%.install: debian/%.install.in
 | 
			
		||||
	sed 's|@LIBDIR@|$(LIBDIR)|g' $< > $@
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Install
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
INSTALL_PERM  = 644
 | 
			
		||||
 | 
			
		||||
INSTALL = install
 | 
			
		||||
INSTALL_DIRS = $(INSTALL) -d
 | 
			
		||||
INSTALL_FILES = $(INSTALL) -m $(INSTALL_PERM)
 | 
			
		||||
INSTALL_FILES = $(INSTALL) -m 644
 | 
			
		||||
 | 
			
		||||
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
 | 
			
		||||
INSTALL_LIB_DIR = $(DESTDIR)$(ABS_LIBDIR)
 | 
			
		||||
INSTALL_INCLUDE_DIR = $(DESTDIR)/usr/include/$(NAME)
 | 
			
		||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)/usr/lib/pkgconfig
 | 
			
		||||
INSTALL_PKGCONFIG_DIR = $(DESTDIR)$(ABS_LIBDIR)/pkgconfig
 | 
			
		||||
 | 
			
		||||
install: $(INSTALL_LIB_DIR)
 | 
			
		||||
	$(INSTALL_FILES) $(RELEASE_SO) $(INSTALL_LIB_DIR)
 | 
			
		||||
	$(INSTALL) -m 755 $(RELEASE_SO) $(INSTALL_LIB_DIR)
 | 
			
		||||
	ln -sf $(LIB_SO) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK2)
 | 
			
		||||
	ln -sf $(LIB_SYMLINK2) $(INSTALL_LIB_DIR)/$(LIB_SYMLINK1)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
A library for communicating with Android IRadio binder services,
 | 
			
		||||
built on top of libgbinder.
 | 
			
		||||
							
								
								
									
										169
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
libgbinder-radio (1.5.3) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added RADIO_ACCESS_NETWORKS enum
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 19 Nov 2022 17:48:38 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.5.2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added network scan related types
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 17 Nov 2022 03:12:02 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.5.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Fixed names of IRadio 1.4 and 1.5 responses
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 14 Nov 2022 22:34:08 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.5.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added support for IRadio@1.5
 | 
			
		||||
  * Added support for IRadioConfig@1.2
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 16 Sep 2022 14:13:04 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.12) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Fixed RadioDataRegStateResult_1_4
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sun, 11 Sep 2022 21:37:23 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.11) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added radio_request_user_data()
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 31 Aug 2022 19:10:49 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.10) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Tweaked completion callback criteria
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 15 Apr 2022 21:58:17 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.9) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added IMS types
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 17 Feb 2022 01:47:27 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.8) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Fixed retries of blocking requests
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 19 Jan 2022 03:32:30 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.7) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Fixed owner queue logic
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Mon, 10 Jan 2022 01:03:28 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.6) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added RadioConfig API
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 08 Jan 2022 20:58:06 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.5) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added radio_req_resp2()
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 16 Dec 2021 01:18:54 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.4) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added IRadio@1.2 IndicationFilter bits
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 14 Dec 2021 18:01:43 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.3) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added RadioClient and related APIs
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 02 Dec 2021 19:08:47 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Don't assume that GBinderServiceManager is a GObject
 | 
			
		||||
  * Added unit tests
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sun, 12 Sep 2021 18:05:19 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added RADIO_CELL_INFO_TYPE_1_4 enum
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 20 May 2021 16:32:16 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.4.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Support for radio@1.4 interfaces
 | 
			
		||||
  * Fixed RadioCellInfo_1_4 definition
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Tue, 18 May 2021 18:54:52 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.6) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added RadioSimApdu type
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sun, 25 Apr 2021 14:41:32 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.5) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added radio@1.3 types
 | 
			
		||||
  * Added radio@1.4 types
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 25 Mar 2021 20:13:08 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.4) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added more radio@1.2 types
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Sat, 20 Mar 2021 02:41:07 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.3) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Reformatted radio@1.2 types
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 19 Mar 2021 05:21:52 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added radio_instance_get_with_version()
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 05 Mar 2021 14:00:20 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Fixed backward compatibility with radio@1.0
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Fri, 05 Mar 2021 12:33:50 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.2.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Support for radio@1.2 interfaces
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 04 Mar 2021 13:36:51 +0200
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.0.11) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Make library executable on RPM based systems
 | 
			
		||||
  * Added req => resp mapping for radio@1.1 calls
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Thu, 01 Oct 2020 21:04:59 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.0.10) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Hide internal symbols
 | 
			
		||||
  * Respect arch specific lib dir
 | 
			
		||||
  * Ignore GLib deprecation warnings
 | 
			
		||||
  * Added constants for android.hardware.radio@1.1 interfaces
 | 
			
		||||
 | 
			
		||||
 -- Slava Monich <slava.monich@jolla.com>  Wed, 03 Jun 2020 15:24:17 +0300
 | 
			
		||||
 | 
			
		||||
libgbinder-radio (1.0.9) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Added packaging for Debian-based distros.
 | 
			
		||||
 | 
			
		||||
 -- Danct12 <danct12@disroot.org>  Tue, 24 Mar 2020 02:55:50 +0700
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
9
 | 
			
		||||
							
								
								
									
										17
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
Source: libgbinder-radio
 | 
			
		||||
Priority: optional
 | 
			
		||||
Maintainer: Danct12 <danct12@disroot.org>
 | 
			
		||||
Build-Depends: debhelper (>=9), libgbinder-dev (>= 1.1.14), libglibutil-dev (>= 1.0.49)
 | 
			
		||||
Standards-Version: 3.9.6
 | 
			
		||||
 | 
			
		||||
Package: libgbinder-radio-dev
 | 
			
		||||
Section: libdevel
 | 
			
		||||
Architecture: any
 | 
			
		||||
Depends: libgbinder-radio (= ${binary:Version}), ${misc:Depends}
 | 
			
		||||
Description: Development files for libgbinder-radio
 | 
			
		||||
 | 
			
		||||
Package: libgbinder-radio
 | 
			
		||||
Section: libs
 | 
			
		||||
Architecture: any
 | 
			
		||||
Depends: libgbinder (>= 1.1.14), libglibutil (>= 1.0.49), ${shlibs:Depends}, ${misc:Depends}
 | 
			
		||||
Description: Binder client library for Android radio interfaces
 | 
			
		||||
							
								
								
									
										33
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 | 
			
		||||
You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
 | 
			
		||||
  1. Redistributions of source code must retain the above copyright
 | 
			
		||||
     notice, this list of conditions and the following disclaimer.
 | 
			
		||||
  2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
     notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
     documentation and/or other materials provided with the distribution.
 | 
			
		||||
  3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
     contributors may be used to endorse or promote products derived
 | 
			
		||||
     from this software without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
The views and conclusions contained in the software and documentation
 | 
			
		||||
are those of the authors and should not be interpreted as representing
 | 
			
		||||
any official policies, either expressed or implied.
 | 
			
		||||
							
								
								
									
										3
									
								
								debian/libgbinder-radio-dev.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								debian/libgbinder-radio-dev.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
debian/tmp/@LIBDIR@/libgbinder-radio.so @LIBDIR@
 | 
			
		||||
debian/tmp/@LIBDIR@/pkgconfig/libgbinder-radio.pc @LIBDIR@/pkgconfig
 | 
			
		||||
debian/tmp/usr/include/* usr/include
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/libgbinder-radio.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libgbinder-radio.install.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
debian/tmp/@LIBDIR@/libgbinder-radio.so.* @LIBDIR@
 | 
			
		||||
							
								
								
									
										14
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#!/usr/bin/make -f
 | 
			
		||||
# Uncomment to enable verbose build
 | 
			
		||||
#export DH_VERBOSE = 1
 | 
			
		||||
 | 
			
		||||
LIBDIR=usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
 | 
			
		||||
 | 
			
		||||
override_dh_auto_build:
 | 
			
		||||
	dh_auto_build -- LIBDIR=$(LIBDIR) release pkgconfig debian/libgbinder-radio.install debian/libgbinder-radio-dev.install
 | 
			
		||||
 | 
			
		||||
override_dh_auto_install:
 | 
			
		||||
	dh_auto_install -- LIBDIR=$(LIBDIR) install-dev
 | 
			
		||||
 | 
			
		||||
%:
 | 
			
		||||
	dh $@ 
 | 
			
		||||
							
								
								
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
3.0 (native)
 | 
			
		||||
							
								
								
									
										143
									
								
								include/radio_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								include/radio_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_CLIENT_H
 | 
			
		||||
#define RADIO_CLIENT_H
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
#include <radio_types.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioClientIndicationFunc)(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioClientFunc)(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
RadioClient*
 | 
			
		||||
radio_client_new(
 | 
			
		||||
    RadioInstance* instance)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioClient*
 | 
			
		||||
radio_client_ref(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_unref(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
RADIO_INTERFACE
 | 
			
		||||
radio_client_interface(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_client_slot(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_dead(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_connected(
 | 
			
		||||
    RadioClient* client);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_set_default_timeout(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    int milliseconds);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_indication_handler(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RadioClientIndicationFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_owner_changed_handler(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RadioClientFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_death_handler(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RadioClientFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_connected_handler(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RadioClientFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_remove_handler(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    gulong id);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_remove_handlers(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    gulong* ids,
 | 
			
		||||
    int count);
 | 
			
		||||
 | 
			
		||||
#define radio_client_remove_all_handlers(client,ids) \
 | 
			
		||||
    radio_client_remove_handlers(client, ids, G_N_ELEMENTS(ids))
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_CLIENT_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										197
									
								
								include/radio_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								include/radio_config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_CONFIG_H
 | 
			
		||||
#define RADIO_CONFIG_H
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.6 */
 | 
			
		||||
 | 
			
		||||
#include <radio_config_types.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioConfigFunc)(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioConfigRequestObserverFunc)(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioConfigResponseObserverFunc)(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_RESP code,
 | 
			
		||||
    const RadioResponseInfo* info,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioConfigIndicationObserverFunc)(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
RadioConfig*
 | 
			
		||||
radio_config_new(void)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioConfig*
 | 
			
		||||
radio_config_new_with_version(
 | 
			
		||||
    RADIO_CONFIG_INTERFACE max_version)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioConfig*
 | 
			
		||||
radio_config_ref(
 | 
			
		||||
    RadioConfig* config);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_config_unref(
 | 
			
		||||
    RadioConfig* config);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_config_dead(
 | 
			
		||||
    RadioConfig* config);
 | 
			
		||||
 | 
			
		||||
RADIO_CONFIG_INTERFACE
 | 
			
		||||
radio_config_interface(
 | 
			
		||||
    RadioConfig* config);
 | 
			
		||||
 | 
			
		||||
gsize
 | 
			
		||||
radio_config_rpc_header_size(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ req);
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_config_req_name(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ req);
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_config_resp_name(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_RESP resp);
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_config_ind_name(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND ind);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_death_handler(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RadioConfigFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_request_observer(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    RadioConfigRequestObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_request_observer_with_priority(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    RadioConfigRequestObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_response_observer(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_RESP code,
 | 
			
		||||
    RadioConfigResponseObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_response_observer_with_priority(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_CONFIG_RESP code,
 | 
			
		||||
    RadioConfigResponseObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_indication_observer(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    RadioConfigIndicationObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_config_add_indication_observer_with_priority(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    RadioConfigIndicationObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_config_remove_handler(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    gulong id);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_config_remove_handlers(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    gulong* ids,
 | 
			
		||||
    int count);
 | 
			
		||||
 | 
			
		||||
#define radio_config_remove_all_handlers(config,ids) \
 | 
			
		||||
    radio_config_remove_handlers(config, ids, G_N_ELEMENTS(ids))
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_CONFIG_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										207
									
								
								include/radio_config_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								include/radio_config_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,207 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_CONFIG_TYPES_H
 | 
			
		||||
#define RADIO_CONFIG_TYPES_H
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.6 */
 | 
			
		||||
 | 
			
		||||
#include <radio_types.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef enum radio_config_interface {
 | 
			
		||||
    RADIO_CONFIG_INTERFACE_NONE = -1,
 | 
			
		||||
    RADIO_CONFIG_INTERFACE_1_0,
 | 
			
		||||
    RADIO_CONFIG_INTERFACE_1_1,
 | 
			
		||||
    RADIO_CONFIG_INTERFACE_1_2, /* Since 1.5.0 */
 | 
			
		||||
    RADIO_CONFIG_INTERFACE_COUNT
 | 
			
		||||
} RADIO_CONFIG_INTERFACE;
 | 
			
		||||
 | 
			
		||||
#define RADIO_CONFIG_INTERFACE_MAX (RADIO_CONFIG_INTERFACE_COUNT - 1)
 | 
			
		||||
 | 
			
		||||
#define RADIO_CONFIG_INSTANCE         "default"
 | 
			
		||||
#define RADIO_CONFIG_IFACE_PREFIX     "android.hardware.radio.config@"
 | 
			
		||||
#define RADIO_CONFIG_IFACE            "IRadioConfig"
 | 
			
		||||
#define RADIO_CONFIG_RESPONSE_IFACE   "IRadioConfigResponse"
 | 
			
		||||
#define RADIO_CONFIG_INDICATION_IFACE "IRadioConfigIndication"
 | 
			
		||||
#define RADIO_CONFIG_IFACE_1_0(x)     RADIO_CONFIG_IFACE_PREFIX "1.0::" x
 | 
			
		||||
#define RADIO_CONFIG_IFACE_1_1(x)     RADIO_CONFIG_IFACE_PREFIX "1.1::" x
 | 
			
		||||
#define RADIO_CONFIG_IFACE_1_2(x)     RADIO_CONFIG_IFACE_PREFIX "1.2::" x
 | 
			
		||||
#define RADIO_CONFIG_1_0              RADIO_CONFIG_IFACE_1_0(RADIO_CONFIG_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_1_1              RADIO_CONFIG_IFACE_1_1(RADIO_CONFIG_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_1_2              RADIO_CONFIG_IFACE_1_2(RADIO_CONFIG_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_1_0_FQNAME       RADIO_CONFIG_1_0 "/" RADIO_CONFIG_INSTANCE
 | 
			
		||||
#define RADIO_CONFIG_1_1_FQNAME       RADIO_CONFIG_1_1 "/" RADIO_CONFIG_INSTANCE
 | 
			
		||||
#define RADIO_CONFIG_1_2_FQNAME       RADIO_CONFIG_1_2 "/" RADIO_CONFIG_INSTANCE
 | 
			
		||||
#define RADIO_CONFIG_RESPONSE_1_0 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_0(RADIO_CONFIG_RESPONSE_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_RESPONSE_1_1 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_1(RADIO_CONFIG_RESPONSE_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_RESPONSE_1_2 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_2(RADIO_CONFIG_RESPONSE_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_INDICATION_1_0 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_0(RADIO_CONFIG_INDICATION_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_INDICATION_1_1 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_1(RADIO_CONFIG_INDICATION_IFACE)
 | 
			
		||||
#define RADIO_CONFIG_INDICATION_1_2 \
 | 
			
		||||
        RADIO_CONFIG_IFACE_1_2(RADIO_CONFIG_INDICATION_IFACE)
 | 
			
		||||
 | 
			
		||||
/* Types defined in types.hal */
 | 
			
		||||
 | 
			
		||||
/* SlotState */
 | 
			
		||||
typedef enum radio_slot_state {
 | 
			
		||||
    RADIO_SLOT_STATE_INACTIVE,
 | 
			
		||||
    RADIO_SLOT_STATE_ACTIVE
 | 
			
		||||
} RADIO_SLOT_STATE;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RADIO_SLOT_STATE) == 4);
 | 
			
		||||
 | 
			
		||||
/* SimSlotStatus */
 | 
			
		||||
typedef struct radio_sim_slot_status {
 | 
			
		||||
    RADIO_CARD_STATE cardState RADIO_ALIGNED(4);
 | 
			
		||||
    RADIO_SLOT_STATE slotState RADIO_ALIGNED(4);
 | 
			
		||||
    GBinderHidlString atr RADIO_ALIGNED(8);
 | 
			
		||||
    guint32 logicalSlotId RADIO_ALIGNED(4);
 | 
			
		||||
    GBinderHidlString iccid RADIO_ALIGNED(8);
 | 
			
		||||
} RADIO_ALIGNED(8) RadioSimSlotStatus;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RadioSimSlotStatus) == 48);
 | 
			
		||||
 | 
			
		||||
/* ModemInfo */
 | 
			
		||||
typedef struct radio_modem_info {
 | 
			
		||||
    guint8 modemId RADIO_ALIGNED(1);
 | 
			
		||||
} RADIO_ALIGNED(1) RadioModemInfo;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RadioModemInfo) == 1);
 | 
			
		||||
 | 
			
		||||
/* PhoneCapability */
 | 
			
		||||
typedef struct radio_phone_capability {
 | 
			
		||||
    guint8 maxActiveData RADIO_ALIGNED(1);
 | 
			
		||||
    guint8 maxActiveInternetData RADIO_ALIGNED(1);
 | 
			
		||||
    guint8 isInternetLingeringSupported RADIO_ALIGNED(1);
 | 
			
		||||
    GBinderHidlVec logicalModemList RADIO_ALIGNED(8); /* vec<ModemInfo> */
 | 
			
		||||
} RADIO_ALIGNED(8) RadioPhoneCapability;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RadioPhoneCapability) == 24);
 | 
			
		||||
 | 
			
		||||
/* ModemsConfig */
 | 
			
		||||
typedef struct radio_modems_config {
 | 
			
		||||
    guint8 numOfLiveModems RADIO_ALIGNED(1);
 | 
			
		||||
} RADIO_ALIGNED(1) RadioModemsConfig;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RadioModemsConfig) == 1);
 | 
			
		||||
 | 
			
		||||
/* Transaction codes */
 | 
			
		||||
 | 
			
		||||
/* c(req,resp,Name,CALL_NAME) */
 | 
			
		||||
#define RADIO_CONFIG_CALL_1_0(c) \
 | 
			
		||||
    c(2,1,getSimSlotsStatus,GET_SIM_SLOTS_STATUS) \
 | 
			
		||||
    c(3,2,setSimSlotsMapping,SET_SIM_SLOTS_MAPPING)
 | 
			
		||||
 | 
			
		||||
#define RADIO_CONFIG_CALL_1_1(c) \
 | 
			
		||||
    c(4,3,getPhoneCapability,GET_PHONE_CAPABILITY) \
 | 
			
		||||
    c(5,4,setPreferredDataModem,SET_PREFERRED_DATA_MODEM) \
 | 
			
		||||
    c(6,5,setModemsConfig,SET_MODEMS_CONFIG) \
 | 
			
		||||
    c(7,6,getModemsConfig,GET_MODEMS_CONFIG)
 | 
			
		||||
 | 
			
		||||
/* i(code,Name,IND_NAME) */
 | 
			
		||||
#define RADIO_CONFIG_IND_1_0(i) \
 | 
			
		||||
    i(1,simSlotsStatusChanged,SIM_SLOTS_STATUS_CHANGED)
 | 
			
		||||
 | 
			
		||||
#define RADIO_CONFIG_IND_1_2(i) \
 | 
			
		||||
    i(2,simSlotsStatusChanged_1_2,SIM_SLOTS_STATUS_CHANGED_1_2) /* Since 1.5.0 */
 | 
			
		||||
 | 
			
		||||
typedef enum radio_config_req {
 | 
			
		||||
    RADIO_CONFIG_REQ_ANY = 0,
 | 
			
		||||
    RADIO_CONFIG_REQ_NONE = 0,
 | 
			
		||||
#define RADIO_CONFIG_REQ_(req,resp,Name,NAME) RADIO_CONFIG_REQ_##NAME = req,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.0::IRadioConfig */
 | 
			
		||||
    RADIO_CONFIG_REQ_SET_RESPONSE_FUNCTIONS = 1, /* setResponseFunctions */
 | 
			
		||||
    RADIO_CONFIG_CALL_1_0(RADIO_CONFIG_REQ_)
 | 
			
		||||
    RADIO_CONFIG_1_0_REQ_LAST = RADIO_CONFIG_REQ_SET_SIM_SLOTS_MAPPING,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.1::IRadioConfig */
 | 
			
		||||
    RADIO_CONFIG_CALL_1_1(RADIO_CONFIG_REQ_)
 | 
			
		||||
    RADIO_CONFIG_1_1_REQ_LAST = RADIO_CONFIG_REQ_GET_MODEMS_CONFIG
 | 
			
		||||
 | 
			
		||||
#undef RADIO_CONFIG_REQ_
 | 
			
		||||
} RADIO_CONFIG_REQ;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RADIO_CONFIG_REQ) == 4);
 | 
			
		||||
 | 
			
		||||
typedef enum radio_config_resp {
 | 
			
		||||
    RADIO_CONFIG_RESP_ANY = 0,
 | 
			
		||||
    RADIO_CONFIG_RESP_NONE = 0,
 | 
			
		||||
#define RADIO_CONFIG_RESP_(req,resp,Name,NAME) RADIO_CONFIG_RESP_##NAME = resp,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.0::IRadioConfigResponse */
 | 
			
		||||
    RADIO_CONFIG_CALL_1_0(RADIO_CONFIG_RESP_)
 | 
			
		||||
    RADIO_CONFIG_1_0_RESP_LAST = RADIO_CONFIG_RESP_SET_SIM_SLOTS_MAPPING,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.1::IRadioConfigResponse */
 | 
			
		||||
    RADIO_CONFIG_CALL_1_1(RADIO_CONFIG_RESP_)
 | 
			
		||||
    RADIO_CONFIG_1_1_RESP_LAST = RADIO_CONFIG_RESP_GET_MODEMS_CONFIG,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.2::IRadioConfigResponse */
 | 
			
		||||
    RADIO_CONFIG_RESP_GET_SIM_SLOTS_STATUS_1_2 = 7, /* Since 1.5.0 */
 | 
			
		||||
    RADIO_CONFIG_1_2_RESP_LAST = RADIO_CONFIG_RESP_GET_SIM_SLOTS_STATUS_1_2
 | 
			
		||||
#undef RADIO_CONFIG_RESP_
 | 
			
		||||
} RADIO_CONFIG_RESP;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RADIO_CONFIG_RESP) == 4);
 | 
			
		||||
 | 
			
		||||
typedef enum radio_config_ind {
 | 
			
		||||
    RADIO_CONFIG_IND_ANY = 0,
 | 
			
		||||
    RADIO_CONFIG_IND_NONE = 0,
 | 
			
		||||
#define RADIO_CONFIG_IND_(code,Name,NAME) RADIO_CONFIG_IND_##NAME = code,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.0::IRadioConfigIndication */
 | 
			
		||||
    RADIO_CONFIG_IND_1_0(RADIO_CONFIG_IND_)
 | 
			
		||||
    RADIO_CONFIG_1_0_IND_LAST = RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED,
 | 
			
		||||
 | 
			
		||||
    /* android.hardware.radio.config@1.2::IRadioConfigIndication */
 | 
			
		||||
    RADIO_CONFIG_IND_1_2(RADIO_CONFIG_IND_) /* Since 1.5.0 */
 | 
			
		||||
    RADIO_CONFIG_1_2_IND_LAST = RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED_1_2
 | 
			
		||||
#undef RADIO_CONFIG_IND_
 | 
			
		||||
} RADIO_CONFIG_IND;
 | 
			
		||||
G_STATIC_ASSERT(sizeof(RADIO_CONFIG_IND) == 4);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_CONFIG_TYPES_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -52,13 +52,21 @@ struct radio_instance {
 | 
			
		||||
    const char* dev;
 | 
			
		||||
    const char* slot;
 | 
			
		||||
    const char* key;
 | 
			
		||||
    /* Since 1.0.7 */
 | 
			
		||||
    const char* modem;  /* D-Bus path */
 | 
			
		||||
    int slot_index;     /* 0 for SIM1, 1 for SIM2 and so on */
 | 
			
		||||
    gboolean enabled;
 | 
			
		||||
    /* Since 1.2.0 */
 | 
			
		||||
    RADIO_INTERFACE version;
 | 
			
		||||
    /* Since 1.4.3 */
 | 
			
		||||
    gboolean connected; /* rilConnected received */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct radio_response_info {
 | 
			
		||||
    RADIO_RESP_TYPE type;
 | 
			
		||||
    guint32 serial;
 | 
			
		||||
    guint32 error;
 | 
			
		||||
} RadioResponseInfo;
 | 
			
		||||
/* These were introduced in 1.4.3 and then renamed in 1.4.6 */
 | 
			
		||||
#define RADIO_INSTANCE_PRIORITY_LOWEST RADIO_OBSERVER_PRIORITY_LOWEST
 | 
			
		||||
#define RADIO_INSTANCE_PRIORITY_DEFAULT RADIO_OBSERVER_PRIORITY_DEFAULT
 | 
			
		||||
#define RADIO_INSTANCE_PRIORITY_HIGHEST RADIO_OBSERVER_PRIORITY_HIGHEST
 | 
			
		||||
#define RADIO_INSTANCE_PRIORITY RADIO_OBSERVER_PRIORITY
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
@@ -66,6 +74,14 @@ void
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioRequestObserverFunc)(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
gboolean
 | 
			
		||||
(*RadioResponseHandlerFunc)(
 | 
			
		||||
@@ -119,11 +135,38 @@ radio_instance_new(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name);
 | 
			
		||||
 | 
			
		||||
RadioInstance*
 | 
			
		||||
radio_instance_new_with_modem_and_slot(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    const char* modem,
 | 
			
		||||
    int slot_index); /* Since 1.0.7 */
 | 
			
		||||
 | 
			
		||||
RadioInstance*
 | 
			
		||||
radio_instance_new_with_version(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    RADIO_INTERFACE version); /* Since 1.2.1 */
 | 
			
		||||
 | 
			
		||||
RadioInstance*
 | 
			
		||||
radio_instance_new_with_modem_slot_and_version(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    const char* modem,
 | 
			
		||||
    int slot_index,
 | 
			
		||||
    RADIO_INTERFACE version); /* Since 1.2.1 */
 | 
			
		||||
 | 
			
		||||
RadioInstance*
 | 
			
		||||
radio_instance_get(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name);
 | 
			
		||||
 | 
			
		||||
RadioInstance*
 | 
			
		||||
radio_instance_get_with_version(
 | 
			
		||||
    const char* dev,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    RADIO_INTERFACE version); /* Since 1.2.2 */
 | 
			
		||||
 | 
			
		||||
RadioInstance* const*
 | 
			
		||||
radio_instance_get_all(
 | 
			
		||||
    void);
 | 
			
		||||
@@ -136,6 +179,11 @@ void
 | 
			
		||||
radio_instance_unref(
 | 
			
		||||
    RadioInstance* radio);
 | 
			
		||||
 | 
			
		||||
gsize
 | 
			
		||||
radio_instance_rpc_header_size(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_REQ req); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_instance_req_name(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
@@ -166,13 +214,41 @@ radio_instance_send_request_sync(
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_indication_handler(
 | 
			
		||||
void
 | 
			
		||||
radio_instance_set_enabled(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RadioIndicationHandlerFunc func,
 | 
			
		||||
    gboolean enabled); /* Since 1.0.7 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_request_observer(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    RadioRequestObserverFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_request_observer_with_priority(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    RadioRequestObserverFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_response_observer(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_RESP code,
 | 
			
		||||
    RadioResponseObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_response_observer_with_priority(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_RESP code,
 | 
			
		||||
    RadioResponseObserverFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_indication_observer(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
@@ -180,6 +256,14 @@ radio_instance_add_indication_observer(
 | 
			
		||||
    RadioIndicationObserverFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_indication_observer_with_priority(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RadioIndicationObserverFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_response_handler(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
@@ -188,10 +272,10 @@ radio_instance_add_response_handler(
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_response_observer(
 | 
			
		||||
radio_instance_add_indication_handler(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RADIO_RESP code,
 | 
			
		||||
    RadioResponseObserverFunc func,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RadioIndicationHandlerFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
@@ -206,6 +290,18 @@ radio_instance_add_death_handler(
 | 
			
		||||
    RadioInstanceFunc func,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_enabled_handler(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RadioInstanceFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.0.7 */
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_add_connected_handler(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    RadioInstanceFunc func,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_instance_remove_handler(
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										224
									
								
								include/radio_request.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								include/radio_request.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,224 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_REQUEST_H
 | 
			
		||||
#define RADIO_REQUEST_H
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
#include <radio_config_types.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Basic workflow
 | 
			
		||||
 *
 | 
			
		||||
 * 1. radio_request_new() or radio_request_new2() creates the request.
 | 
			
		||||
 *    That assigns a serial and initializes GBinderWriter for appending
 | 
			
		||||
 *    more arguments. GBinderWriter pointer can be NULL if serial is the
 | 
			
		||||
 *    only argument.
 | 
			
		||||
 * 2. The caller (optionally) uses GBinderWriter to add more arguments
 | 
			
		||||
 *    to the request.
 | 
			
		||||
 * 3. radio_request_submit() submits the request
 | 
			
		||||
 * 4. radio_request_unref() can be called at this point to release the
 | 
			
		||||
 *    reference produced by radio_request_new() unless the caller needs
 | 
			
		||||
 *    to keep it. In any case, radio_request_unref() has to be called
 | 
			
		||||
 *    sooner or later for each request created by radio_request_new().
 | 
			
		||||
 *    The library keeps its own internal reference while the request is
 | 
			
		||||
 *    being processed.
 | 
			
		||||
 * 5. RadioRequestCompleteFunc receives the response from the radio service.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef enum radio_tx_status {
 | 
			
		||||
    RADIO_TX_STATUS_OK,       /* Successful completion, no error */
 | 
			
		||||
    RADIO_TX_STATUS_FAILED,   /* Request transaction failed */
 | 
			
		||||
    RADIO_TX_STATUS_TIMEOUT   /* No response transaction received */
 | 
			
		||||
} RADIO_TX_STATUS;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RadioRequestCompleteFunc
 | 
			
		||||
 * RadioConfigRequestCompleteFunc
 | 
			
		||||
 *
 | 
			
		||||
 * Invoked upon completion of each request. If an error occurs,
 | 
			
		||||
 * resp is set to zero (RADIO_RESP_NONE, RADIO_CONFIG_RESP_NONE)
 | 
			
		||||
 * and args is NULL.
 | 
			
		||||
 *
 | 
			
		||||
 * The status argument is the status of the request transaction.
 | 
			
		||||
 * If it's anything other than RADIO_TX_STATUS_OK, the request
 | 
			
		||||
 * transaction failed (or response didn't arrive in time) and
 | 
			
		||||
 * the other arguments can be ignored.
 | 
			
		||||
 *
 | 
			
		||||
 * If status is RADIO_TX_STATUS_OK then the resp, error and args
 | 
			
		||||
 * arguments contain the information received in the response.
 | 
			
		||||
 */
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioRequestCompleteFunc)(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioConfigRequestCompleteFunc)(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_CONFIG_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data); /* Since 1.4.6 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * RadioRequestRetryFunc
 | 
			
		||||
 *
 | 
			
		||||
 * If retries are enabled with radio_request_set_retry_func(), then this
 | 
			
		||||
 * callback is invoiked to check whether the request should be retried,
 | 
			
		||||
 * based on the status received from the radio service and the contents
 | 
			
		||||
 * of the reply. If such callback returns TRUE, the request is retried
 | 
			
		||||
 * at some point in the future with a new serial, otherwise it gets
 | 
			
		||||
 * completed right away.
 | 
			
		||||
 *
 | 
			
		||||
 * user_data is the pointer passed to radio_request_new() when the request
 | 
			
		||||
 * was created.
 | 
			
		||||
 */
 | 
			
		||||
typedef
 | 
			
		||||
gboolean
 | 
			
		||||
(*RadioRequestRetryFunc)(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    guint32 resp, /* Was RADIO_RESP before 1.4.6 */
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    void* user_data);
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_new(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderWriter* args, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_new2(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderWriter* args, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_config_request_new(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    GBinderWriter* args, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioConfigRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data) /* Since 1.4.6 */
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_ref(
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_unref(
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_blocking(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    gboolean blocking);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_timeout(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint milliseconds); /* Zero to use the default timeout */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_retry(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint delay_ms,     /* Delay before each retry, in milliseconds */
 | 
			
		||||
    int max_count);     /* Negative count to keep retrying indefinitely */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_retry_func(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RadioRequestRetryFunc retry);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_request_submit(
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_request_retry(
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_cancel(
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_drop( /* cancel and unref */
 | 
			
		||||
    RadioRequest* req);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_retry_func(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RadioRequestRetryFunc retry);
 | 
			
		||||
 | 
			
		||||
void*
 | 
			
		||||
radio_request_user_data(
 | 
			
		||||
    RadioRequest* req); /* Since 1.4.11 */
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_REQUEST_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										96
									
								
								include/radio_request_group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								include/radio_request_group.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_REQUEST_GROUP_H
 | 
			
		||||
#define RADIO_REQUEST_GROUP_H
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
#include <radio_types.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * In addition to being just a group of requests and making it easier
 | 
			
		||||
 * to perform bulk operations (i.e. cancel all), RadioRequestGroup can
 | 
			
		||||
 * be given the "blocker" status by its RadioClient and then only requests
 | 
			
		||||
 * belonging to this group will be submitted until the block is released.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
struct radio_request_group {
 | 
			
		||||
    RadioClient* client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RadioRequestGroup*
 | 
			
		||||
radio_request_group_new(
 | 
			
		||||
    RadioClient* client)
 | 
			
		||||
    G_GNUC_WARN_UNUSED_RESULT;
 | 
			
		||||
 | 
			
		||||
RadioRequestGroup*
 | 
			
		||||
radio_request_group_ref(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_unref(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_cancel(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_request_group_block_status(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_request_group_block(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_unblock(
 | 
			
		||||
    RadioRequestGroup* group);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_REQUEST_GROUP_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -55,7 +55,13 @@ radio_ind_name(
 | 
			
		||||
 | 
			
		||||
RADIO_RESP
 | 
			
		||||
radio_req_resp(
 | 
			
		||||
    RADIO_REQ req);
 | 
			
		||||
    RADIO_REQ req)
 | 
			
		||||
    G_GNUC_DEPRECATED_FOR(radio_req_resp2);
 | 
			
		||||
 | 
			
		||||
RADIO_RESP
 | 
			
		||||
radio_req_resp2(
 | 
			
		||||
    RADIO_REQ req,
 | 
			
		||||
    RADIO_INTERFACE iface); /* Since 1.4.5 */
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
name=gbinder-radio
 | 
			
		||||
libdir=/usr/lib
 | 
			
		||||
libdir=@libdir@
 | 
			
		||||
includedir=/usr/include
 | 
			
		||||
 | 
			
		||||
Name: libgbinder-radio
 | 
			
		||||
Description: Binder client library for Android radio interfaces
 | 
			
		||||
Version: [version]
 | 
			
		||||
Requires: glib-2.0 libglibutil libgbinder
 | 
			
		||||
Version: @version@
 | 
			
		||||
Requires.private: glib-2.0 libglibutil libgbinder
 | 
			
		||||
Libs: -L${libdir} -l${name}
 | 
			
		||||
Cflags: -I${includedir} -I${includedir}/${name}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,26 @@
 | 
			
		||||
Name: libgbinder-radio
 | 
			
		||||
Version: 0.0.1
 | 
			
		||||
 | 
			
		||||
Version: 1.5.3
 | 
			
		||||
Release: 0
 | 
			
		||||
Summary: Binder client library for Android radio interfaces
 | 
			
		||||
Group: Development/Libraries
 | 
			
		||||
License: BSD
 | 
			
		||||
URL: https://github.com/mer-hybris/libgbinder-radio
 | 
			
		||||
Source: %{name}-%{version}.tar.bz2
 | 
			
		||||
 | 
			
		||||
%define libgbinder_version 1.1.14
 | 
			
		||||
%define libglibutil_version 1.0.49
 | 
			
		||||
 | 
			
		||||
BuildRequires: pkgconfig
 | 
			
		||||
BuildRequires: pkgconfig(glib-2.0)
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil)
 | 
			
		||||
BuildRequires: pkgconfig(libgbinder)
 | 
			
		||||
BuildRequires: pkgconfig(libglibutil) >= %{libglibutil_version}
 | 
			
		||||
BuildRequires: pkgconfig(libgbinder) >= %{libgbinder_version}
 | 
			
		||||
 | 
			
		||||
# license macro requires rpm >= 4.11
 | 
			
		||||
BuildRequires: pkgconfig(rpm)
 | 
			
		||||
%define license_support %(pkg-config --exists 'rpm >= 4.11'; echo $?)
 | 
			
		||||
 | 
			
		||||
Requires: libglibutil >= %{libglibutil_version}
 | 
			
		||||
Requires: libgbinder >= %{libgbinder_version}
 | 
			
		||||
Requires(post): /sbin/ldconfig
 | 
			
		||||
Requires(postun): /sbin/ldconfig
 | 
			
		||||
 | 
			
		||||
@@ -18,7 +30,6 @@ Binder client library for Android radio interfaces
 | 
			
		||||
%package devel
 | 
			
		||||
Summary: Development library for %{name}
 | 
			
		||||
Requires: %{name} = %{version}
 | 
			
		||||
Requires: pkgconfig
 | 
			
		||||
 | 
			
		||||
%description devel
 | 
			
		||||
This package contains the development library for %{name}.
 | 
			
		||||
@@ -27,11 +38,14 @@ This package contains the development library for %{name}.
 | 
			
		||||
%setup -q
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
make KEEP_SYMBOLS=1 release pkgconfig
 | 
			
		||||
make %{_smp_mflags} LIBDIR=%{_libdir} KEEP_SYMBOLS=1 release pkgconfig
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
rm -rf %{buildroot}
 | 
			
		||||
make install-dev DESTDIR=%{buildroot}
 | 
			
		||||
make LIBDIR=%{_libdir} DESTDIR=%{buildroot} install-dev
 | 
			
		||||
 | 
			
		||||
%check
 | 
			
		||||
make -C unit test
 | 
			
		||||
 | 
			
		||||
%post -p /sbin/ldconfig
 | 
			
		||||
 | 
			
		||||
@@ -40,6 +54,9 @@ make install-dev DESTDIR=%{buildroot}
 | 
			
		||||
%files
 | 
			
		||||
%defattr(-,root,root,-)
 | 
			
		||||
%{_libdir}/%{name}.so.*
 | 
			
		||||
%if %{license_support} == 0
 | 
			
		||||
%license LICENSE
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%files devel
 | 
			
		||||
%defattr(-,root,root,-)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1014
									
								
								src/radio_base.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1014
									
								
								src/radio_base.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										198
									
								
								src/radio_base.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								src/radio_base.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,198 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_BASE_H
 | 
			
		||||
#define RADIO_BASE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
/* RadioBaseFunc must be compatible with RadioClientFunc */
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioBaseFunc)(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioBaseRequestSentFunc)(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    int status);
 | 
			
		||||
 | 
			
		||||
typedef struct radio_base_priv RadioBasePriv;
 | 
			
		||||
 | 
			
		||||
struct radio_base {
 | 
			
		||||
    GObject object;
 | 
			
		||||
    RadioBasePriv* priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct radio_base_class {
 | 
			
		||||
    GObjectClass parent;
 | 
			
		||||
    gboolean (*is_dead)(RadioBase* base);
 | 
			
		||||
    gboolean (*can_submit_requests)(RadioBase* base);
 | 
			
		||||
    GBinderLocalRequest* (*new_request)(RadioBase* base, guint32 code);
 | 
			
		||||
    gulong (*send_request)(RadioBase* base, RadioRequest* req,
 | 
			
		||||
        RadioBaseRequestSentFunc sent);
 | 
			
		||||
    void (*cancel_request)(RadioBase* base, gulong id);
 | 
			
		||||
} RadioBaseClass;
 | 
			
		||||
 | 
			
		||||
GType radio_base_get_type(void) RADIO_INTERNAL;
 | 
			
		||||
#define RADIO_TYPE_BASE radio_base_get_type()
 | 
			
		||||
#define RADIO_BASE(obj) G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
        RADIO_TYPE_BASE, RadioBase)
 | 
			
		||||
#define RADIO_BASE_CLASS(klass) G_TYPE_CHECK_CLASS_CAST((klass), \
 | 
			
		||||
        RADIO_TYPE_BASE, RadioBaseClass)
 | 
			
		||||
#define RADIO_BASE_GET_CLASS(obj) G_TYPE_INSTANCE_GET_CLASS((obj), \
 | 
			
		||||
        THIS_TYPE, RadioBaseClass)
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_initialize(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_register_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_unregister_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_base_submit_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_base_retry_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_request_dropped(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
radio_base_timeout_ms(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_reset_timeout(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_base_block_status(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_base_block(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_unblock(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_base_handle_resp(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    const RadioResponseInfo* info,
 | 
			
		||||
    const GBinderReader* reader)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_handle_ack(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    guint32 serial)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_handle_death(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_submit_requests(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_cancel_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_base_set_default_timeout(
 | 
			
		||||
    RadioBase* self,
 | 
			
		||||
    int ms)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_base_add_owner_changed_handler(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioBaseFunc func,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_BASE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										473
									
								
								src/radio_client.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								src/radio_client.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,473 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "radio_base.h"
 | 
			
		||||
#include "radio_client.h"
 | 
			
		||||
#include "radio_instance_p.h"
 | 
			
		||||
#include "radio_request_p.h"
 | 
			
		||||
#include "radio_util.h"
 | 
			
		||||
#include "radio_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
#include <gutil_misc.h>
 | 
			
		||||
 | 
			
		||||
/* This API exists since 1.4.3 */
 | 
			
		||||
 | 
			
		||||
enum radio_events {
 | 
			
		||||
    RADIO_EVENT_IND,
 | 
			
		||||
    RADIO_EVENT_RESP,
 | 
			
		||||
    RADIO_EVENT_ACK,
 | 
			
		||||
    RADIO_EVENT_DEATH,
 | 
			
		||||
    RADIO_EVENT_CONNECTED,
 | 
			
		||||
    RADIO_EVENT_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct radio_client {
 | 
			
		||||
    RadioBase base;
 | 
			
		||||
    RadioInstance* instance;
 | 
			
		||||
    gulong event_ids[RADIO_EVENT_COUNT];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef RadioBaseClass RadioClientClass;
 | 
			
		||||
GType radio_client_get_type() RADIO_INTERNAL;
 | 
			
		||||
G_DEFINE_TYPE(RadioClient, radio_client, RADIO_TYPE_BASE)
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS radio_client_parent_class
 | 
			
		||||
#define THIS_TYPE radio_client_get_type()
 | 
			
		||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, THIS_TYPE, RadioClient)
 | 
			
		||||
 | 
			
		||||
typedef struct radio_client_call {
 | 
			
		||||
    RadioRequest* req;
 | 
			
		||||
    RadioBaseRequestSentFunc callback;
 | 
			
		||||
} RadioClientCall;
 | 
			
		||||
 | 
			
		||||
enum radio_client_signal {
 | 
			
		||||
    SIGNAL_INDICATION,
 | 
			
		||||
    SIGNAL_DEATH,
 | 
			
		||||
    SIGNAL_CONNECTED,
 | 
			
		||||
    SIGNAL_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SIGNAL_INDICATION_NAME "radio-client-indication"
 | 
			
		||||
#define SIGNAL_DEATH_NAME      "radio-client-death"
 | 
			
		||||
#define SIGNAL_CONNECTED_NAME  "radio-client-connected"
 | 
			
		||||
 | 
			
		||||
static guint radio_client_signals[SIGNAL_COUNT] = { 0 };
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Implementation
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_call_free(
 | 
			
		||||
    RadioClientCall* call)
 | 
			
		||||
{
 | 
			
		||||
    radio_request_unref(call->req);
 | 
			
		||||
    gutil_slice_free(call);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_call_destroy(
 | 
			
		||||
    void* user_data1,
 | 
			
		||||
    void* user_data2)
 | 
			
		||||
{
 | 
			
		||||
    radio_client_call_free(user_data2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_call_complete(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    gulong id,
 | 
			
		||||
    int status,
 | 
			
		||||
    void* user_data1,
 | 
			
		||||
    void* user_data2)
 | 
			
		||||
{
 | 
			
		||||
    RadioClientCall* call = user_data2;
 | 
			
		||||
 | 
			
		||||
    call->callback(RADIO_BASE(user_data1), call->req, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_handle_death(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    RadioBase* base = RADIO_BASE(user_data);
 | 
			
		||||
 | 
			
		||||
    g_object_ref(base);
 | 
			
		||||
    radio_base_handle_death(base);
 | 
			
		||||
    g_signal_emit(base, radio_client_signals[SIGNAL_DEATH], 0);
 | 
			
		||||
    g_object_unref(base);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_handle_connected(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit(THIS(user_data), radio_client_signals[SIGNAL_CONNECTED], 0);
 | 
			
		||||
    radio_base_submit_requests(RADIO_BASE(user_data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_handle_ack(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    guint32 serial,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    radio_base_handle_ack(RADIO_BASE(user_data), serial);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_handle_ind(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RADIO_IND_TYPE type,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit(THIS(user_data), radio_client_signals[SIGNAL_INDICATION],
 | 
			
		||||
        radio_instance_ind_quark(instance, code), code, reader);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_handle_resp(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    RADIO_RESP code,
 | 
			
		||||
    const RadioResponseInfo* info,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    if (!radio_base_handle_resp(RADIO_BASE(user_data), code, info, reader)) {
 | 
			
		||||
        const char* name = radio_resp_name(code);
 | 
			
		||||
 | 
			
		||||
        /* Most likely this is a response to a cancelled request */
 | 
			
		||||
        GDEBUG("Ignoring IRadio response [%08x] %u %s", info->serial, code,
 | 
			
		||||
            name ? name : "");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    enum radio_client_signal sig,
 | 
			
		||||
    RadioClientFunc fn,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    return (G_LIKELY(self) && G_LIKELY(fn)) ?
 | 
			
		||||
        g_signal_connect_closure_by_id(self, radio_client_signals[sig], 0,
 | 
			
		||||
             g_cclosure_new(G_CALLBACK(fn), user_data, NULL), FALSE) : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
RadioClient*
 | 
			
		||||
radio_client_new(
 | 
			
		||||
    RadioInstance* instance)
 | 
			
		||||
{
 | 
			
		||||
    RadioClient* self = NULL;
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(instance)) {
 | 
			
		||||
        self = g_object_new(THIS_TYPE, NULL);
 | 
			
		||||
        radio_base_initialize(&self->base);
 | 
			
		||||
        self->instance = radio_instance_ref(instance);
 | 
			
		||||
        self->event_ids[RADIO_EVENT_IND] =
 | 
			
		||||
            radio_instance_add_indication_observer(instance, RADIO_IND_ANY,
 | 
			
		||||
                radio_client_handle_ind, self);
 | 
			
		||||
        self->event_ids[RADIO_EVENT_RESP] =
 | 
			
		||||
            radio_instance_add_response_observer(instance, RADIO_RESP_ANY,
 | 
			
		||||
                radio_client_handle_resp, self);
 | 
			
		||||
        self->event_ids[RADIO_EVENT_ACK] =
 | 
			
		||||
            radio_instance_add_ack_handler(instance,
 | 
			
		||||
                radio_client_handle_ack, self);
 | 
			
		||||
        self->event_ids[RADIO_EVENT_DEATH] =
 | 
			
		||||
            radio_instance_add_death_handler(instance,
 | 
			
		||||
                radio_client_handle_death, self);
 | 
			
		||||
        self->event_ids[RADIO_EVENT_CONNECTED] =
 | 
			
		||||
            radio_instance_add_connected_handler(instance,
 | 
			
		||||
                radio_client_handle_connected, self);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioClient*
 | 
			
		||||
radio_client_ref(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_ref(self);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_unref(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        g_object_unref(self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_client_slot(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    return G_LIKELY(self) ? self->instance->slot : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_dead(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    return !self || self->instance->dead;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_connected(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    return self && self->instance->connected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RADIO_INTERFACE
 | 
			
		||||
radio_client_interface(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
    return G_LIKELY(self) ? self->instance->version : RADIO_INTERFACE_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_set_default_timeout(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    int milliseconds)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        radio_base_set_default_timeout(&self->base, milliseconds);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_indication_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    RADIO_IND code,
 | 
			
		||||
    RadioClientIndicationFunc fn,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    return (G_LIKELY(self) && G_LIKELY(fn)) ?
 | 
			
		||||
        g_signal_connect_closure_by_id(self,
 | 
			
		||||
            radio_client_signals[SIGNAL_INDICATION],
 | 
			
		||||
            radio_instance_ind_quark(self->instance, code),
 | 
			
		||||
            g_cclosure_new(G_CALLBACK(fn), user_data, NULL), FALSE) : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_owner_changed_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    RadioClientFunc fn,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    return self ? radio_base_add_owner_changed_handler(&self->base,
 | 
			
		||||
        (RadioBaseFunc) fn, user_data) : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_death_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    RadioClientFunc fn,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    return radio_client_add_handler(self, SIGNAL_DEATH, fn, user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_add_connected_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    RadioClientFunc fn,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    return radio_client_add_handler(self, SIGNAL_CONNECTED, fn, user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_remove_handler(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    gulong id)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(id) && G_LIKELY(self)) {
 | 
			
		||||
        g_signal_handler_disconnect(self, id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_client_remove_handlers(
 | 
			
		||||
    RadioClient* self,
 | 
			
		||||
    gulong* ids,
 | 
			
		||||
    int count)
 | 
			
		||||
{
 | 
			
		||||
    gutil_disconnect_handlers(self, ids, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Methods
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_is_dead(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
{
 | 
			
		||||
    return THIS(base)->instance->dead;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
radio_client_can_submit_requests(
 | 
			
		||||
    RadioBase* base)
 | 
			
		||||
{
 | 
			
		||||
    return THIS(base)->instance->connected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
radio_client_new_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    guint32 code)
 | 
			
		||||
{
 | 
			
		||||
    return radio_instance_new_request(THIS(base)->instance, code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gulong
 | 
			
		||||
radio_client_send_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RadioBaseRequestSentFunc callback)
 | 
			
		||||
{
 | 
			
		||||
    RadioClientCall* call = g_slice_new(RadioClientCall);
 | 
			
		||||
    gulong tx_id;
 | 
			
		||||
 | 
			
		||||
    call->callback = callback;
 | 
			
		||||
    call->req = radio_request_ref(req);
 | 
			
		||||
    tx_id = radio_instance_send_request(THIS(base)->instance,
 | 
			
		||||
        req->code, req->args, radio_client_call_complete,
 | 
			
		||||
        radio_client_call_destroy, base, call);
 | 
			
		||||
    if (tx_id) {
 | 
			
		||||
        return tx_id;
 | 
			
		||||
    } else {
 | 
			
		||||
        radio_client_call_free(call);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_cancel_request(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    gulong id)
 | 
			
		||||
{
 | 
			
		||||
    radio_instance_cancel_request(THIS(base)->instance, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internals
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_init(
 | 
			
		||||
    RadioClient* self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    RadioClient* self = THIS(object);
 | 
			
		||||
 | 
			
		||||
    radio_instance_remove_all_handlers(self->instance, self->event_ids);
 | 
			
		||||
    radio_instance_unref(self->instance);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_client_class_init(
 | 
			
		||||
    RadioClientClass* klass)
 | 
			
		||||
{
 | 
			
		||||
    RadioBaseClass* base_class = RADIO_BASE_CLASS(klass);
 | 
			
		||||
    GObjectClass* object_class = G_OBJECT_CLASS(klass);
 | 
			
		||||
    GType type = G_OBJECT_CLASS_TYPE(klass);
 | 
			
		||||
 | 
			
		||||
    base_class->is_dead = radio_client_is_dead;
 | 
			
		||||
    base_class->can_submit_requests = radio_client_can_submit_requests;
 | 
			
		||||
    base_class->new_request = radio_client_new_request;
 | 
			
		||||
    base_class->send_request = radio_client_send_request;
 | 
			
		||||
    base_class->cancel_request = radio_client_cancel_request;
 | 
			
		||||
    object_class->finalize = radio_client_finalize;
 | 
			
		||||
 | 
			
		||||
    radio_client_signals[SIGNAL_INDICATION] =
 | 
			
		||||
        g_signal_new(SIGNAL_INDICATION_NAME, type,
 | 
			
		||||
            G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED, 0, NULL, NULL, NULL,
 | 
			
		||||
            G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER);
 | 
			
		||||
    radio_client_signals[SIGNAL_DEATH] =
 | 
			
		||||
        g_signal_new(SIGNAL_DEATH_NAME, type, G_SIGNAL_RUN_FIRST, 0,
 | 
			
		||||
            NULL, NULL, NULL, G_TYPE_NONE, 0);
 | 
			
		||||
    radio_client_signals[SIGNAL_CONNECTED] =
 | 
			
		||||
        g_signal_new(SIGNAL_CONNECTED_NAME, type, G_SIGNAL_RUN_FIRST, 0,
 | 
			
		||||
            NULL, NULL, NULL, G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										1008
									
								
								src/radio_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1008
									
								
								src/radio_config.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										89
									
								
								src/radio_instance_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/radio_instance_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_INSTANCE_PRIVATE_H
 | 
			
		||||
#define RADIO_INSTANCE_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
#include "radio_instance.h"
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioInstanceTxCompleteFunc)(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    gulong id,
 | 
			
		||||
    int status,
 | 
			
		||||
    void* user_data1,
 | 
			
		||||
    void* user_data2);
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioInstanceTxDestroyFunc)(
 | 
			
		||||
    void* user_data1,
 | 
			
		||||
    void* user_data2);
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
radio_instance_send_request(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args,
 | 
			
		||||
    RadioInstanceTxCompleteFunc complete,
 | 
			
		||||
    RadioInstanceTxDestroyFunc destroy,
 | 
			
		||||
    void* user_data1,
 | 
			
		||||
    void* user_data2)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_instance_cancel_request(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    gulong id)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
GQuark
 | 
			
		||||
radio_instance_ind_quark(
 | 
			
		||||
    RadioInstance* instance,
 | 
			
		||||
    RADIO_IND ind)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_INSTANCE_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -44,6 +44,7 @@ struct radio_registry {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType radio_registry_get_type(void) RADIO_INTERNAL;
 | 
			
		||||
G_DEFINE_TYPE(RadioRegistry, radio_registry, G_TYPE_OBJECT)
 | 
			
		||||
#define RADIO_TYPE_REGISTRY (radio_registry_get_type())
 | 
			
		||||
#define RADIO_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
 | 
			
		||||
@@ -110,7 +111,7 @@ radio_registry_new(
 | 
			
		||||
            (gpointer*)(&radio_registry_instance));
 | 
			
		||||
    }
 | 
			
		||||
    return radio_registry_instance;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioRegistry*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -37,15 +37,18 @@
 | 
			
		||||
#ifndef RADIO_REGISTRY_PRIVATE_H
 | 
			
		||||
#define RADIO_REGISTRY_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
#include "radio_registry.h"
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_registry_instance_added(
 | 
			
		||||
    RadioInstance* instance);
 | 
			
		||||
    RadioInstance* instance)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_registry_instance_removed(
 | 
			
		||||
    const char* key);
 | 
			
		||||
    const char* key)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_REGISTRY_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										382
									
								
								src/radio_request.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										382
									
								
								src/radio_request.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,382 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "radio_base.h"
 | 
			
		||||
#include "radio_request_p.h"
 | 
			
		||||
#include "radio_request_group_p.h"
 | 
			
		||||
#include "radio_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gbinder_local_request.h>
 | 
			
		||||
#include <gbinder_writer.h>
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
typedef enum radio_request_flags {
 | 
			
		||||
    RADIO_REQUEST_NO_FLAGS = 0,
 | 
			
		||||
    RADIO_REQUEST_FLAG_DROPPED = 0x01,
 | 
			
		||||
    RADIO_REQUEST_FLAG_SUBMITTED = 0x02
 | 
			
		||||
} RADIO_REQUEST_FLAGS;
 | 
			
		||||
 | 
			
		||||
typedef struct radio_request_object {
 | 
			
		||||
    RadioRequest pub;
 | 
			
		||||
    GDestroyNotify destroy;
 | 
			
		||||
    gsize serial_offset;
 | 
			
		||||
    RADIO_REQUEST_FLAGS flags;
 | 
			
		||||
    gint refcount;
 | 
			
		||||
} RadioRequestObject;
 | 
			
		||||
 | 
			
		||||
static inline RadioRequestObject* radio_request_cast(RadioRequest* req)
 | 
			
		||||
    { return req ? G_CAST(req, RadioRequestObject, pub) : NULL; }
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Implementation
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_request_object_cancel(
 | 
			
		||||
    RadioRequestObject* self)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequest* req = &self->pub;
 | 
			
		||||
 | 
			
		||||
    radio_base_cancel_request(req->object, req);
 | 
			
		||||
    if (!(self->flags & RADIO_REQUEST_FLAG_DROPPED)) {
 | 
			
		||||
        self->flags |= RADIO_REQUEST_FLAG_DROPPED;
 | 
			
		||||
        radio_request_group_remove(req->group, req);
 | 
			
		||||
        radio_base_request_dropped(req);
 | 
			
		||||
    }
 | 
			
		||||
    radio_base_unregister_request(req->object, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_request_free(
 | 
			
		||||
    RadioRequestObject* self)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequest* req = &self->pub;
 | 
			
		||||
 | 
			
		||||
    GVERBOSE_("%u (%08x) %p", req->code, req->serial, req);
 | 
			
		||||
    radio_request_object_cancel(self);
 | 
			
		||||
 | 
			
		||||
    /* Don't invoke completion routine if the request was never submitted */
 | 
			
		||||
    if (req->complete && (self->flags & RADIO_REQUEST_FLAG_SUBMITTED)) {
 | 
			
		||||
        RadioRequestCompleteFunc complete = req->complete;
 | 
			
		||||
 | 
			
		||||
        /* Request is being freed too early, before completion */
 | 
			
		||||
        req->complete = NULL;
 | 
			
		||||
        complete(req, RADIO_TX_STATUS_FAILED, RADIO_RESP_NONE,
 | 
			
		||||
            RADIO_ERROR_NONE, NULL, req->user_data);
 | 
			
		||||
    }
 | 
			
		||||
    if (self->destroy) {
 | 
			
		||||
        GDestroyNotify destroy = self->destroy;
 | 
			
		||||
 | 
			
		||||
        self->destroy = NULL;
 | 
			
		||||
        destroy(req->user_data);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_local_request_unref(req->args);
 | 
			
		||||
    gutil_slice_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_request_object_unref(
 | 
			
		||||
    RadioRequestObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GASSERT(self->refcount > 0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            radio_request_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
radio_request_default_retry(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    if (status != RADIO_TX_STATUS_OK) {
 | 
			
		||||
        GVERBOSE_("req %p %u (%08x) status %d", req, req->code, req->serial,
 | 
			
		||||
            status);
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    } else if (error != RADIO_ERROR_NONE) {
 | 
			
		||||
        GVERBOSE_("req %p %u (%08x) error %d", req, req->code, req->serial,
 | 
			
		||||
            error);
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    } else {
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_object_new(
 | 
			
		||||
    RadioBase* base,
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    RadioRequestGenericCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestObject* self = g_slice_new0(RadioRequestObject);
 | 
			
		||||
    RadioRequest* req = &self->pub;
 | 
			
		||||
    GBinderWriter tmp;
 | 
			
		||||
 | 
			
		||||
    self->destroy = destroy;
 | 
			
		||||
    g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
 | 
			
		||||
    req->state = RADIO_REQUEST_STATE_NEW;
 | 
			
		||||
    req->code = code;
 | 
			
		||||
    req->complete = complete;
 | 
			
		||||
    req->user_data = user_data;
 | 
			
		||||
    req->retry = radio_request_default_retry;
 | 
			
		||||
 | 
			
		||||
    /* Assign serial and add to the group */
 | 
			
		||||
    radio_base_register_request(base, req);
 | 
			
		||||
    radio_request_group_add(group, req);
 | 
			
		||||
    GVERBOSE_("%u (%08x) %p group %p", req->code, req->serial, req, group);
 | 
			
		||||
 | 
			
		||||
    /* Build the argument list */
 | 
			
		||||
    if (!writer) writer = &tmp;
 | 
			
		||||
    req->args = RADIO_BASE_GET_CLASS(base)->new_request(base, code);
 | 
			
		||||
    gbinder_local_request_init_writer(req->args, writer);
 | 
			
		||||
    self->serial_offset = gbinder_writer_bytes_written(writer);
 | 
			
		||||
    gbinder_writer_append_int32(writer, req->serial);
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_unref_func(
 | 
			
		||||
    gpointer req)
 | 
			
		||||
{
 | 
			
		||||
    radio_request_object_unref(radio_request_cast(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_update_serial(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint32 serial)
 | 
			
		||||
{
 | 
			
		||||
    GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
    gbinder_local_request_init_writer(req->args, &writer);
 | 
			
		||||
    gbinder_writer_overwrite_int32(&writer,
 | 
			
		||||
        radio_request_cast(req)->serial_offset, serial);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_new(
 | 
			
		||||
    RadioClient* client,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderWriter* writer, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    return client ? radio_request_object_new(RADIO_BASE(client), NULL,
 | 
			
		||||
        code, writer, (RadioRequestGenericCompleteFunc) complete,
 | 
			
		||||
        destroy, user_data) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_new2(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RADIO_REQ code,
 | 
			
		||||
    GBinderWriter* writer, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    return group ? radio_request_object_new(RADIO_BASE(group->client), group,
 | 
			
		||||
        code, writer, (RadioRequestGenericCompleteFunc) complete,
 | 
			
		||||
        destroy, user_data) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_config_request_new(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    GBinderWriter* writer, /* NULL if serial is the only arg */
 | 
			
		||||
    RadioConfigRequestCompleteFunc complete,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data) /* Since 1.4.6 */
 | 
			
		||||
{
 | 
			
		||||
    return config ? radio_request_object_new(RADIO_BASE(config), NULL,
 | 
			
		||||
        code, writer, (RadioRequestGenericCompleteFunc) complete,
 | 
			
		||||
        destroy, user_data) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioRequest*
 | 
			
		||||
radio_request_ref(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestObject* self = radio_request_cast(req);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GASSERT(self->refcount > 0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return req;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_unref(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    radio_request_object_unref(radio_request_cast(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_blocking(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    gboolean blocking)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(req)) {
 | 
			
		||||
        req->blocking = blocking;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_timeout(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint ms)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(req) && req->timeout_ms != ms) {
 | 
			
		||||
        RadioBase* base = req->object;
 | 
			
		||||
 | 
			
		||||
        req->timeout_ms = ms;
 | 
			
		||||
        if (base && req->state >= RADIO_REQUEST_STATE_QUEUED) {
 | 
			
		||||
            const guint timeout = radio_base_timeout_ms(base, req);
 | 
			
		||||
 | 
			
		||||
            req->deadline = g_get_monotonic_time() + MICROSEC(timeout);
 | 
			
		||||
            radio_base_reset_timeout(base);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_retry(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint delay_ms,     /* Delay before each retry, in milliseconds */
 | 
			
		||||
    int max_count)      /* Negative count to keep retrying indefinitely */
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(req)) {
 | 
			
		||||
        req->retry_delay_ms = delay_ms;
 | 
			
		||||
        req->max_retries = max_count;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_set_retry_func(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RadioRequestRetryFunc retry)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(req)) {
 | 
			
		||||
        req->retry = retry ? retry : radio_request_default_retry;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_request_submit(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    if (req && req->object && radio_base_submit_request(req->object, req)) {
 | 
			
		||||
        radio_request_cast(req)->flags |= RADIO_REQUEST_FLAG_SUBMITTED;
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
radio_request_retry(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    return req && req->object && radio_base_retry_request(req->object, req);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_cancel(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestObject* self = radio_request_cast(req);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        req->complete = NULL;
 | 
			
		||||
        radio_request_object_cancel(self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_drop(
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestObject* self = radio_request_cast(req);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        req->complete = NULL;
 | 
			
		||||
        radio_request_object_cancel(self);
 | 
			
		||||
        radio_request_object_unref(self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void*
 | 
			
		||||
radio_request_user_data(
 | 
			
		||||
    RadioRequest* req) /* Since 1.4.11 */
 | 
			
		||||
{
 | 
			
		||||
    return G_LIKELY(req) ? req->user_data : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										224
									
								
								src/radio_request_group.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								src/radio_request_group.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,224 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "radio_base.h"
 | 
			
		||||
#include "radio_client.h"
 | 
			
		||||
#include "radio_request_group_p.h"
 | 
			
		||||
#include "radio_request_p.h"
 | 
			
		||||
#include "radio_log.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_macros.h>
 | 
			
		||||
 | 
			
		||||
typedef struct radio_request_group_object {
 | 
			
		||||
    RadioRequestGroup pub;
 | 
			
		||||
    GHashTable* requests;
 | 
			
		||||
    gint refcount;
 | 
			
		||||
} RadioRequestGroupObject;
 | 
			
		||||
 | 
			
		||||
static inline RadioRequestGroupObject*
 | 
			
		||||
radio_request_group_cast(RadioRequestGroup* group)
 | 
			
		||||
    { return group ? G_CAST(group, RadioRequestGroupObject, pub) : NULL; }
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Implementation
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_unlink_func(
 | 
			
		||||
    gpointer req)
 | 
			
		||||
{
 | 
			
		||||
    ((RadioRequest*)req)->group = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_free(
 | 
			
		||||
    RadioRequestGroupObject* self)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroup* group = &self->pub;
 | 
			
		||||
 | 
			
		||||
    radio_base_unblock(RADIO_BASE(group->client), group);
 | 
			
		||||
    g_hash_table_destroy(self->requests);
 | 
			
		||||
    radio_client_unref(group->client);
 | 
			
		||||
    gutil_slice_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_add(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroupObject* self = radio_request_group_cast(group);
 | 
			
		||||
 | 
			
		||||
    /* Request is never NULL but the group may be */
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_hash_table_insert(self->requests, req, req);
 | 
			
		||||
        req->group = group;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_remove(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroupObject* self = radio_request_group_cast(group);
 | 
			
		||||
 | 
			
		||||
    /* Request is never NULL but the group may be */
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_hash_table_remove(self->requests, req);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
RadioRequestGroup*
 | 
			
		||||
radio_request_group_new(
 | 
			
		||||
    RadioClient* client)
 | 
			
		||||
{
 | 
			
		||||
    if (G_LIKELY(client)) {
 | 
			
		||||
        RadioRequestGroupObject* self = g_slice_new0(RadioRequestGroupObject);
 | 
			
		||||
        RadioRequestGroup* group = &self->pub;
 | 
			
		||||
 | 
			
		||||
        group->client = radio_client_ref(client);
 | 
			
		||||
        self->requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 | 
			
		||||
            NULL, radio_request_group_unlink_func);
 | 
			
		||||
        g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
        return group;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioRequestGroup*
 | 
			
		||||
radio_request_group_ref(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroupObject* self = radio_request_group_cast(group);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GASSERT(self->refcount > 0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_unref(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroupObject* self = radio_request_group_cast(group);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GASSERT(self->refcount > 0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            radio_request_group_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_cancel(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    RadioRequestGroupObject* self = radio_request_group_cast(group);
 | 
			
		||||
 | 
			
		||||
    if (G_LIKELY(self)) {
 | 
			
		||||
        GHashTableIter it;
 | 
			
		||||
        gpointer value;
 | 
			
		||||
        GSList* list = NULL;
 | 
			
		||||
        GSList* l;
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Move requests to the list and temporarily reference them
 | 
			
		||||
         * before invoking any callbacks.
 | 
			
		||||
         */
 | 
			
		||||
        g_hash_table_iter_init(&it, self->requests);
 | 
			
		||||
        while (g_hash_table_iter_next(&it, NULL, &value)) {
 | 
			
		||||
            list = g_slist_prepend(list, radio_request_ref(value));
 | 
			
		||||
            g_hash_table_iter_remove(&it);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Actually cancel the requests. This invokes completion callbacks.
 | 
			
		||||
         * The group is already empty at this point.
 | 
			
		||||
         */
 | 
			
		||||
        for (l = list; l; l = l->next) {
 | 
			
		||||
            radio_request_cancel(l->data);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Release the temporary references */
 | 
			
		||||
        g_slist_free_full(list, radio_request_unref_func);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_request_group_block_status(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    return group ? radio_base_block_status(RADIO_BASE(group->client), group) :
 | 
			
		||||
        RADIO_BLOCK_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RADIO_BLOCK
 | 
			
		||||
radio_request_group_block(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    return group ? radio_base_block(RADIO_BASE(group->client), group) :
 | 
			
		||||
        RADIO_BLOCK_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_unblock(
 | 
			
		||||
    RadioRequestGroup* group)
 | 
			
		||||
{
 | 
			
		||||
    if (group) {
 | 
			
		||||
        radio_base_unblock(RADIO_BASE(group->client), group);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										63
									
								
								src/radio_request_group_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/radio_request_group_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_REQUEST_GROUP_PRIVATE_H
 | 
			
		||||
#define RADIO_REQUEST_GROUP_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
#include <radio_request_group.h>
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_add(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_group_remove(
 | 
			
		||||
    RadioRequestGroup* group,
 | 
			
		||||
    RadioRequest* req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_REQUEST_GROUP_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										162
									
								
								src/radio_request_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/radio_request_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_REQUEST_PRIVATE_H
 | 
			
		||||
#define RADIO_REQUEST_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
#include "radio_request.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Request lifecycle
 | 
			
		||||
 * =================
 | 
			
		||||
 *
 | 
			
		||||
 *        +=====+
 | 
			
		||||
 *        | NEW | ----------------------[cancel]------------+
 | 
			
		||||
 *        +=====+                                           |
 | 
			
		||||
 *           |                                              |
 | 
			
		||||
 *        [submit]                                          |
 | 
			
		||||
 *           |                                              |
 | 
			
		||||
 *           |                                              |
 | 
			
		||||
 *    +----> +---------------+                              |
 | 
			
		||||
 *    |      |               |                              |
 | 
			
		||||
 *    |      |           (blocked)                          |
 | 
			
		||||
 *    |  (unblocked)         |                              |
 | 
			
		||||
 *    |      |               v                              v
 | 
			
		||||
 *    |      |           +========+                   +===========+
 | 
			
		||||
 * (retry)   |           | QUEUED | ----[cancel]----> | CANCELLED |
 | 
			
		||||
 *    |      |           +========+                   +===========+
 | 
			
		||||
 *    |      |               |                              ^
 | 
			
		||||
 *    |      |           (unblocked)                        |
 | 
			
		||||
 *    |      |               |                              |
 | 
			
		||||
 *    |      |    +----------+                              |
 | 
			
		||||
 *    |      |    |                                         |
 | 
			
		||||
 *    |      v    v                                         |
 | 
			
		||||
 *    |  +-------------+                                    |
 | 
			
		||||
 *    |  |   submit    |                +========+          |
 | 
			
		||||
 *    |  |  request    | ---(error)---> | FAILED |          |
 | 
			
		||||
 *    |  | transaction |                +========+          |
 | 
			
		||||
 *    |  +-------------+                    ^               |
 | 
			
		||||
 *    |         |                           |               |
 | 
			
		||||
 *    |        (ok)     +---(error)---------+               |
 | 
			
		||||
 *    |         |      /                                    |
 | 
			
		||||
 *    |         v     /                                     |
 | 
			
		||||
 *    |    +=========+                  +=========+         |
 | 
			
		||||
 *    +--- | PENDING | ---(timeout)---> | TIMEOUT |         |
 | 
			
		||||
 *         +=========+                  +=========+         |
 | 
			
		||||
 *           |        \                                     |
 | 
			
		||||
 *           |         +----------------[cancel]------------+
 | 
			
		||||
 *      (response)
 | 
			
		||||
 *           |
 | 
			
		||||
 *           v
 | 
			
		||||
 *        +======+
 | 
			
		||||
 *        | DONE |
 | 
			
		||||
 *        +======+
 | 
			
		||||
 *
 | 
			
		||||
 * Timeout starts ticking when request enters the PENDING state.
 | 
			
		||||
 * The library maintains an internal reference to the request in
 | 
			
		||||
 * QUEUED and PENDING states.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef enum radio_request_state {
 | 
			
		||||
    RADIO_REQUEST_STATE_INVALID,
 | 
			
		||||
    RADIO_REQUEST_STATE_NEW,
 | 
			
		||||
    RADIO_REQUEST_STATE_QUEUED,
 | 
			
		||||
    RADIO_REQUEST_STATE_PENDING,
 | 
			
		||||
    /*
 | 
			
		||||
     * Reorder states carefully or better don't reorder at all.
 | 
			
		||||
     * States >= RADIO_REQUEST_STATE_FAILED are assumed to be
 | 
			
		||||
     * terminal states in the state machine.
 | 
			
		||||
     */
 | 
			
		||||
    RADIO_REQUEST_STATE_FAILED,
 | 
			
		||||
    RADIO_REQUEST_STATE_CANCELLED,
 | 
			
		||||
    RADIO_REQUEST_STATE_TIMEOUT,
 | 
			
		||||
    RADIO_REQUEST_STATE_DONE
 | 
			
		||||
} RADIO_REQUEST_STATE;
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
void
 | 
			
		||||
(*RadioRequestGenericCompleteFunc)(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    guint32 resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data);
 | 
			
		||||
 | 
			
		||||
struct radio_request {
 | 
			
		||||
    RADIO_REQUEST_STATE state;
 | 
			
		||||
    guint32 code;
 | 
			
		||||
    GBinderLocalRequest* args;
 | 
			
		||||
    RadioRequestGenericCompleteFunc complete;
 | 
			
		||||
    RadioRequestRetryFunc retry;
 | 
			
		||||
    void* user_data;
 | 
			
		||||
    guint32 serial;             /* Immutable, generated at creation time */
 | 
			
		||||
    guint32 serial2;            /* Mutable, used by the last transaction */
 | 
			
		||||
    int max_retries;            /* Negative = retry indefinitely */
 | 
			
		||||
    int retry_count;            /* Number of times we have already retried */
 | 
			
		||||
    guint retry_delay_ms;       /* Delay before each retry, in milliseconds */
 | 
			
		||||
    guint timeout_ms;           /* Timeout, in milliseconds (0 = default) */
 | 
			
		||||
    gint64 deadline;            /* Monotonic time, in microseconds */
 | 
			
		||||
    gint64 scheduled;           /* Monotonic time, in microseconds */
 | 
			
		||||
    gulong tx_id;               /* Id of the request transaction */
 | 
			
		||||
    gboolean blocking;          /* TRUE if this request blocks all others */
 | 
			
		||||
    gboolean acked;
 | 
			
		||||
    RadioBase* object;          /* Not a reference */
 | 
			
		||||
    RadioRequestGroup* group;   /* Not a reference */
 | 
			
		||||
    RadioRequest* queue_next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_unref_func(
 | 
			
		||||
    gpointer req)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
radio_request_update_serial(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    guint32 serial)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_REQUEST_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										75
									
								
								src/radio_types_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/radio_types_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_TYPES_PRIVATE_H
 | 
			
		||||
#define RADIO_TYPES_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <radio_types.h>
 | 
			
		||||
 | 
			
		||||
typedef struct radio_base RadioBase;
 | 
			
		||||
 | 
			
		||||
#define RADIO_INTERNAL G_GNUC_INTERNAL
 | 
			
		||||
 | 
			
		||||
/* Miliseconds to microseconds */
 | 
			
		||||
#define MICROSEC(ms) (((gint64)(ms)) * 1000)
 | 
			
		||||
 | 
			
		||||
/* Preprocessor magic related to observers */
 | 
			
		||||
G_STATIC_ASSERT(RADIO_OBSERVER_PRIORITY_LOWEST == 0);
 | 
			
		||||
G_STATIC_ASSERT(RADIO_OBSERVER_PRIORITY_HIGHEST == 7);
 | 
			
		||||
#define FOREACH_OBSERVER_PRIORITY(p) p(0) p(1) p(2) p(3) p(4) p(5) p(6) p(7)
 | 
			
		||||
#define RADIO_OBSERVER_PRIORITY_INDEX(p) ((p) - RADIO_OBSERVER_PRIORITY_LOWEST)
 | 
			
		||||
#define RADIO_OBSERVER_PRIORITY_COUNT \
 | 
			
		||||
    (RADIO_OBSERVER_PRIORITY_INDEX(RADIO_OBSERVER_PRIORITY_HIGHEST) + 1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A special assert fatal in debug build and non-fatal in release.
 | 
			
		||||
 * Marks truely unavoidable conditions.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#  define DEBUG_ASSERT(expr) g_assert(expr)
 | 
			
		||||
#else
 | 
			
		||||
#  define DEBUG_ASSERT(expr)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_TYPES_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										313
									
								
								src/radio_util.c
									
									
									
									
									
								
							
							
						
						
									
										313
									
								
								src/radio_util.c
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2019 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2019 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
@@ -34,11 +34,24 @@
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "radio_util.h"
 | 
			
		||||
#include "radio_util_p.h"
 | 
			
		||||
#include "radio_log.h"
 | 
			
		||||
 | 
			
		||||
GLOG_MODULE_DEFINE("gbinder-radio");
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
radio_observer_priority_index(
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority)
 | 
			
		||||
{
 | 
			
		||||
    if (priority < RADIO_OBSERVER_PRIORITY_LOWEST) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else if (priority > RADIO_OBSERVER_PRIORITY_HIGHEST) {
 | 
			
		||||
        return RADIO_OBSERVER_PRIORITY_COUNT - 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return priority - RADIO_OBSERVER_PRIORITY_LOWEST;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
radio_req_name(
 | 
			
		||||
    RADIO_REQ req)
 | 
			
		||||
@@ -48,8 +61,22 @@ radio_req_name(
 | 
			
		||||
    case RADIO_REQ_RESPONSE_ACKNOWLEDGEMENT: return "responseAcknowledgement";
 | 
			
		||||
#define RADIO_REQ_(req,resp,Name,NAME) \
 | 
			
		||||
    case RADIO_REQ_##NAME: return #Name;
 | 
			
		||||
#define RADIO_REQ__(req,resp,Name,NAME,x) \
 | 
			
		||||
    case RADIO_REQ_##NAME##x: return #Name #x;
 | 
			
		||||
    RADIO_CALL_1_0(RADIO_REQ_)
 | 
			
		||||
    RADIO_CALL_1_1(RADIO_REQ_)
 | 
			
		||||
    RADIO_CALL_1_2(RADIO_REQ_)
 | 
			
		||||
    RADIO_CALL_1_3(RADIO_REQ_)
 | 
			
		||||
    RADIO_CALL_1_4_(RADIO_REQ__)
 | 
			
		||||
    RADIO_CALL_1_5_(RADIO_REQ__)
 | 
			
		||||
#undef RADIO_REQ_
 | 
			
		||||
#undef RADIO_REQ__
 | 
			
		||||
    case RADIO_REQ_START_NETWORK_SCAN_1_2:     return "startNetworkScan_1_2";
 | 
			
		||||
    case RADIO_REQ_SET_INDICATION_FILTER_1_2:  return "setIndicationFilter_1_2";
 | 
			
		||||
    case RADIO_REQ_SETUP_DATA_CALL_1_2:        return "setupDataCall_1_2";
 | 
			
		||||
    case RADIO_REQ_DEACTIVATE_DATA_CALL_1_2:   return "deactivateDataCall_1_2";
 | 
			
		||||
    case RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4: return "setInitialAttachApn_1_4";
 | 
			
		||||
    case RADIO_REQ_SET_DATA_PROFILE_1_4:       return "setDataProfile_1_4";
 | 
			
		||||
    case RADIO_REQ_ANY:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -64,8 +91,42 @@ radio_resp_name(
 | 
			
		||||
    case RADIO_RESP_ACKNOWLEDGE_REQUEST: return "acknowledgeRequest";
 | 
			
		||||
#define RADIO_RESP_(req,resp,Name,NAME) \
 | 
			
		||||
    case RADIO_RESP_##NAME: return #Name "Response";
 | 
			
		||||
#define RADIO_RESP__(req,resp,Name,NAME,x) \
 | 
			
		||||
    case RADIO_RESP_##NAME##x: return #Name "Response" #x;
 | 
			
		||||
    RADIO_CALL_1_0(RADIO_RESP_)
 | 
			
		||||
    RADIO_CALL_1_1(RADIO_RESP_)
 | 
			
		||||
    RADIO_CALL_1_2(RADIO_RESP_)
 | 
			
		||||
    RADIO_CALL_1_3(RADIO_RESP_)
 | 
			
		||||
    RADIO_CALL_1_4_(RADIO_RESP__)
 | 
			
		||||
    RADIO_CALL_1_5_(RADIO_RESP__)
 | 
			
		||||
#undef RADIO_RESP_
 | 
			
		||||
#undef RADIO_RESP__
 | 
			
		||||
    case RADIO_RESP_GET_CELL_INFO_LIST_1_2:
 | 
			
		||||
        return "getCellInfoListResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_ICC_CARD_STATUS_1_2:
 | 
			
		||||
        return "getIccCardStatusResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_CURRENT_CALLS_1_2:
 | 
			
		||||
        return "getCurrentCallsResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_SIGNAL_STRENGTH_1_2:
 | 
			
		||||
        return "getSignalStrengthResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2:
 | 
			
		||||
        return "getVoiceRegistrationStateResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2:
 | 
			
		||||
        return "getDataRegistrationStateResponse_1_2";
 | 
			
		||||
    case RADIO_RESP_GET_CELL_INFO_LIST_RESPONSE_1_4:
 | 
			
		||||
        return "getCellInfoListResponse_1_4";
 | 
			
		||||
    case RADIO_RESP_GET_DATA_REGISTRATION_STATE_RESPONSE_1_4:
 | 
			
		||||
        return "getDataRegistrationStateResponse_1_4";
 | 
			
		||||
    case RADIO_RESP_GET_ICC_CARD_STATUS_RESPONSE_1_4:
 | 
			
		||||
        return "getIccCardStatusResponse_1_4";
 | 
			
		||||
    case RADIO_RESP_GET_DATA_CALL_LIST_RESPONSE_1_4:
 | 
			
		||||
        return "getDataCallListResponse_1_4";
 | 
			
		||||
    case RADIO_RESP_GET_DATA_CALL_LIST_1_5:
 | 
			
		||||
        return "getDataCallList_1_5";
 | 
			
		||||
    case RADIO_RESP_GET_CELL_INFO_LIST_1_5:
 | 
			
		||||
        return "getCellInfoListResponse_1_5";
 | 
			
		||||
    case RADIO_RESP_GET_ICC_CARD_STATUS_1_5:
 | 
			
		||||
        return "getIccCardStatus_1_5";
 | 
			
		||||
    case RADIO_RESP_ANY:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -80,6 +141,10 @@ radio_ind_name(
 | 
			
		||||
#define RADIO_IND_(code,Name,NAME) \
 | 
			
		||||
    case RADIO_IND_##NAME: return #Name;
 | 
			
		||||
    RADIO_EVENT_1_0(RADIO_IND_)
 | 
			
		||||
    RADIO_EVENT_1_1(RADIO_IND_)
 | 
			
		||||
    RADIO_EVENT_1_2(RADIO_IND_)
 | 
			
		||||
    RADIO_EVENT_1_4(RADIO_IND_)
 | 
			
		||||
    RADIO_EVENT_1_5(RADIO_IND_)
 | 
			
		||||
#undef RADIO_IND_
 | 
			
		||||
    case RADIO_IND_ANY:
 | 
			
		||||
        break;
 | 
			
		||||
@@ -87,18 +152,250 @@ radio_ind_name(
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This function no longer makes as much sense as it did in IRadio 1.0 times.
 | 
			
		||||
 * Later it turned out that that same call may produce different responses
 | 
			
		||||
 * under different circumstances. For example, getIccCardStatus call may
 | 
			
		||||
 * cause getIccCardStatusResponse or getIccCardStatusResponse_1_2 to be
 | 
			
		||||
 * sent back, depending on which interfaces are supported by the caller.
 | 
			
		||||
 * There's no longer one-to-one match between requests and responses,
 | 
			
		||||
 * that would be too easy and straightforward for Google designers :)
 | 
			
		||||
 *
 | 
			
		||||
 * Use this function carefully or better don't use it at all.
 | 
			
		||||
 */
 | 
			
		||||
RADIO_RESP
 | 
			
		||||
radio_req_resp(
 | 
			
		||||
    RADIO_REQ req)
 | 
			
		||||
{
 | 
			
		||||
    switch (req) {
 | 
			
		||||
#define RADIO_REQ_(req,resp,Name,NAME) \
 | 
			
		||||
#define RADIO_REQ_RESP_(req,resp,Name,NAME) \
 | 
			
		||||
    case RADIO_REQ_##NAME: return RADIO_RESP_##NAME;
 | 
			
		||||
    RADIO_CALL_1_0(RADIO_REQ_)
 | 
			
		||||
#undef RADIO_REQ_
 | 
			
		||||
    default:
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
#define RADIO_REQ_RESP__(req,resp,Name,NAME,x) \
 | 
			
		||||
    case RADIO_REQ_##NAME##x: return RADIO_RESP_##NAME##x;
 | 
			
		||||
    RADIO_CALL_1_0(RADIO_REQ_RESP_)
 | 
			
		||||
    RADIO_CALL_1_1(RADIO_REQ_RESP_)
 | 
			
		||||
    RADIO_CALL_1_2(RADIO_REQ_RESP_)
 | 
			
		||||
    RADIO_CALL_1_3(RADIO_REQ_RESP_)
 | 
			
		||||
    RADIO_CALL_1_4_(RADIO_REQ_RESP__)
 | 
			
		||||
    RADIO_CALL_1_5_(RADIO_REQ_RESP__)
 | 
			
		||||
#undef RADIO_REQ_RESP_
 | 
			
		||||
#undef RADIO_REQ_RESP__
 | 
			
		||||
    case RADIO_REQ_SETUP_DATA_CALL_1_2:
 | 
			
		||||
        return RADIO_RESP_SETUP_DATA_CALL;
 | 
			
		||||
    case RADIO_REQ_DEACTIVATE_DATA_CALL_1_2:
 | 
			
		||||
        return RADIO_RESP_DEACTIVATE_DATA_CALL;
 | 
			
		||||
    case RADIO_REQ_START_NETWORK_SCAN_1_2:
 | 
			
		||||
        return RADIO_RESP_START_NETWORK_SCAN;
 | 
			
		||||
    case RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4:
 | 
			
		||||
        return RADIO_RESP_SET_INITIAL_ATTACH_APN;
 | 
			
		||||
    case RADIO_REQ_SET_DATA_PROFILE_1_4:
 | 
			
		||||
        return RADIO_RESP_SET_DATA_PROFILE;
 | 
			
		||||
    case RADIO_REQ_SET_INDICATION_FILTER_1_2:
 | 
			
		||||
        return RADIO_RESP_SET_INDICATION_FILTER;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * All these still need to be listed here to ensure a compilation
 | 
			
		||||
     * warnings when something gets added to RADIO_REQ enum.
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_SET_RESPONSE_FUNCTIONS:
 | 
			
		||||
    case RADIO_REQ_RESPONSE_ACKNOWLEDGEMENT:
 | 
			
		||||
    case RADIO_REQ_ANY:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return RADIO_RESP_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * And this is a version of radio_req_resp which takes IRadio interface
 | 
			
		||||
 * version into account. This one is OK to use.
 | 
			
		||||
 */
 | 
			
		||||
RADIO_RESP
 | 
			
		||||
radio_req_resp2(
 | 
			
		||||
    RADIO_REQ req,
 | 
			
		||||
    RADIO_INTERFACE iface) /* Since 1.4.5 */
 | 
			
		||||
{
 | 
			
		||||
    switch (req) {
 | 
			
		||||
    /*
 | 
			
		||||
     * Requests expecting a response from a previous version of the
 | 
			
		||||
     * interface.
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_SETUP_DATA_CALL_1_2:
 | 
			
		||||
        return RADIO_RESP_SETUP_DATA_CALL;
 | 
			
		||||
    case RADIO_REQ_DEACTIVATE_DATA_CALL_1_2:
 | 
			
		||||
        return RADIO_RESP_DEACTIVATE_DATA_CALL;
 | 
			
		||||
    case RADIO_REQ_START_NETWORK_SCAN_1_2:
 | 
			
		||||
        return RADIO_RESP_START_NETWORK_SCAN;
 | 
			
		||||
    case RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4:
 | 
			
		||||
        return RADIO_RESP_SET_INITIAL_ATTACH_APN;
 | 
			
		||||
    case RADIO_REQ_SET_DATA_PROFILE_1_4:
 | 
			
		||||
        return RADIO_RESP_SET_DATA_PROFILE;
 | 
			
		||||
    case RADIO_REQ_SET_INDICATION_FILTER_1_2:
 | 
			
		||||
 /* case RADIO_REQ_SET_INDICATION_FILTER_1_5: */
 | 
			
		||||
        return RADIO_RESP_SET_INDICATION_FILTER;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Requests which may receive a response from a higher version of
 | 
			
		||||
     * the interface.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getIccCardStatus
 | 
			
		||||
     * getIccCardStatusResponse
 | 
			
		||||
     * getIccCardStatusResponse_1_2
 | 
			
		||||
     * getIccCardStatusResponse_1_4
 | 
			
		||||
     * getIccCardStatusResponse_1_5
 | 
			
		||||
     * ...
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_ICC_CARD_STATUS:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_ICC_CARD_STATUS;
 | 
			
		||||
        case RADIO_INTERFACE_1_2:
 | 
			
		||||
        case RADIO_INTERFACE_1_3:
 | 
			
		||||
            return RADIO_RESP_GET_ICC_CARD_STATUS_1_2;
 | 
			
		||||
        case RADIO_INTERFACE_1_4:
 | 
			
		||||
            return RADIO_RESP_GET_ICC_CARD_STATUS_1_4;
 | 
			
		||||
        case RADIO_INTERFACE_1_5:
 | 
			
		||||
            return RADIO_RESP_GET_ICC_CARD_STATUS_1_5;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
        case RADIO_INTERFACE_COUNT:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getCellInfoList
 | 
			
		||||
     * getCellInfoListResponse
 | 
			
		||||
     * getCellInfoListResponse_1_2
 | 
			
		||||
     * getCellInfoListResponse_1_4
 | 
			
		||||
     * getCellInfoListResponse_1_5 <= the last one
 | 
			
		||||
     * getCellInfoList_1_6
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_CELL_INFO_LIST:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_CELL_INFO_LIST;
 | 
			
		||||
        case RADIO_INTERFACE_1_2:
 | 
			
		||||
        case RADIO_INTERFACE_1_3:
 | 
			
		||||
            return RADIO_RESP_GET_CELL_INFO_LIST_1_2;
 | 
			
		||||
        case RADIO_INTERFACE_1_4:
 | 
			
		||||
            return RADIO_RESP_GET_CELL_INFO_LIST_1_4;
 | 
			
		||||
        default:
 | 
			
		||||
            return RADIO_RESP_GET_CELL_INFO_LIST_1_5;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getCurrentCalls
 | 
			
		||||
     * getCurrentCallsResponse
 | 
			
		||||
     * getCurrentCallsResponse_1_2 <= the last one
 | 
			
		||||
     * getCurrentCalls_1_6
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_CURRENT_CALLS:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_CURRENT_CALLS;
 | 
			
		||||
        default: /* The last one */
 | 
			
		||||
            return RADIO_RESP_GET_CURRENT_CALLS_1_2;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getSignalStrength
 | 
			
		||||
     * getSignalStrengthResponse
 | 
			
		||||
     * getSignalStrengthResponse_1_2 <= the last one
 | 
			
		||||
     * getSignalStrength_1_4
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_SIGNAL_STRENGTH:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_SIGNAL_STRENGTH;
 | 
			
		||||
        default: /* The last one */
 | 
			
		||||
            return RADIO_RESP_GET_SIGNAL_STRENGTH_1_2;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getVoiceRegistrationState
 | 
			
		||||
     * getVoiceRegistrationStateResponse
 | 
			
		||||
     * getVoiceRegistrationStateResponse_1_2 <= the last one
 | 
			
		||||
     * getVoiceRegistrationState_1_5
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_VOICE_REGISTRATION_STATE:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_VOICE_REGISTRATION_STATE;
 | 
			
		||||
        default: /* The last one */
 | 
			
		||||
            return RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getDataRegistrationState
 | 
			
		||||
     * getDataRegistrationStateResponse
 | 
			
		||||
     * getDataRegistrationStateResponse_1_2
 | 
			
		||||
     * getDataRegistrationStateResponse_1_4 <= the last one
 | 
			
		||||
     * getDataRegistrationState_1_5
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_DATA_REGISTRATION_STATE:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
            return RADIO_RESP_GET_DATA_REGISTRATION_STATE;
 | 
			
		||||
        case RADIO_INTERFACE_1_2:
 | 
			
		||||
        case RADIO_INTERFACE_1_3:
 | 
			
		||||
            return RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2;
 | 
			
		||||
        default: /* The last one */
 | 
			
		||||
            return RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_4;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * getDataCallList
 | 
			
		||||
     * getDataCallListResponse
 | 
			
		||||
     * getDataCallListResponse_1_4
 | 
			
		||||
     * getDataCallListResponse_1_5 <= the last one
 | 
			
		||||
     * getDataCallList_1_6
 | 
			
		||||
     */
 | 
			
		||||
    case RADIO_REQ_GET_DATA_CALL_LIST:
 | 
			
		||||
        switch (iface) {
 | 
			
		||||
        case RADIO_INTERFACE_1_0:
 | 
			
		||||
        case RADIO_INTERFACE_1_1:
 | 
			
		||||
        case RADIO_INTERFACE_1_2:
 | 
			
		||||
        case RADIO_INTERFACE_1_3:
 | 
			
		||||
            return RADIO_RESP_GET_DATA_CALL_LIST;
 | 
			
		||||
        case RADIO_INTERFACE_1_4:
 | 
			
		||||
            return RADIO_RESP_GET_DATA_CALL_LIST_1_4;
 | 
			
		||||
        default: /* The last one */
 | 
			
		||||
            return RADIO_RESP_GET_DATA_CALL_LIST_1_5;
 | 
			
		||||
        case RADIO_INTERFACE_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        return RADIO_RESP_NONE;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Fallback */
 | 
			
		||||
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | 
			
		||||
    return radio_req_resp(req);
 | 
			
		||||
    G_GNUC_END_IGNORE_DEPRECATIONS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								src/radio_util_p.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/radio_util_p.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef RADIO_UTIL_PRIVATE_H
 | 
			
		||||
#define RADIO_UTIL_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include "radio_types_p.h"
 | 
			
		||||
#include "radio_util.h"
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
radio_observer_priority_index(
 | 
			
		||||
    RADIO_OBSERVER_PRIORITY priority)
 | 
			
		||||
    RADIO_INTERNAL;
 | 
			
		||||
 | 
			
		||||
#endif /* RADIO_UTIL_PRIVATE_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										15
									
								
								unit/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								unit/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: clean all
 | 
			
		||||
 | 
			
		||||
all:
 | 
			
		||||
%:
 | 
			
		||||
	@$(MAKE) -C unit_client $*
 | 
			
		||||
	@$(MAKE) -C unit_config $*
 | 
			
		||||
	@$(MAKE) -C unit_instance $*
 | 
			
		||||
	@$(MAKE) -C unit_registry $*
 | 
			
		||||
	@$(MAKE) -C unit_util $*
 | 
			
		||||
 | 
			
		||||
clean: unitclean
 | 
			
		||||
	rm -f coverage/*.gcov
 | 
			
		||||
	rm -fr coverage/report
 | 
			
		||||
							
								
								
									
										216
									
								
								unit/common/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								unit/common/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,216 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
.PHONY: clean cleaner unitclean all debug release coverage valgrind
 | 
			
		||||
.PHONY: debug_lib release_lib coverage_lib
 | 
			
		||||
.PHONY: test test_banner
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Real test makefile defines EXE (and possibly SRC) and includes this one.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
ifndef EXE
 | 
			
		||||
${error EXE not defined}
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
SRC ?= $(EXE).c
 | 
			
		||||
COMMON_SRC ?= \
 | 
			
		||||
  test_gbinder_client.c \
 | 
			
		||||
  test_gbinder_local_object.c \
 | 
			
		||||
  test_gbinder_local_request.c \
 | 
			
		||||
  test_gbinder_local_reply.c \
 | 
			
		||||
  test_gbinder_reader_writer.c \
 | 
			
		||||
  test_gbinder_remote_object.c \
 | 
			
		||||
  test_gbinder_remote_request.c \
 | 
			
		||||
  test_gbinder_remote_reply.c \
 | 
			
		||||
  test_gbinder_servicemanager.c \
 | 
			
		||||
  test_main.c
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Required packages
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
LINK_PKGS += libglibutil glib-2.0 gobject-2.0
 | 
			
		||||
PKGS += $(LINK_PKGS) libgbinder
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Default target
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
all: debug release
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Directories
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
SRC_DIR = .
 | 
			
		||||
LIB_DIR = ../..
 | 
			
		||||
COMMON_DIR = ../common
 | 
			
		||||
BUILD_DIR = build
 | 
			
		||||
DEBUG_BUILD_DIR = $(BUILD_DIR)/debug
 | 
			
		||||
RELEASE_BUILD_DIR = $(BUILD_DIR)/release
 | 
			
		||||
COVERAGE_BUILD_DIR = $(BUILD_DIR)/coverage
 | 
			
		||||
COMMON_BUILD_DIR = $(COMMON_DIR)/build
 | 
			
		||||
COMMON_DEBUG_BUILD_DIR = $(COMMON_BUILD_DIR)/debug
 | 
			
		||||
COMMON_RELEASE_BUILD_DIR = $(COMMON_BUILD_DIR)/release
 | 
			
		||||
COMMON_COVERAGE_BUILD_DIR = $(COMMON_BUILD_DIR)/coverage
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Tools and flags
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
CC ?= $(CROSS_COMPILE)gcc
 | 
			
		||||
LD = $(CC)
 | 
			
		||||
WARNINGS += -Wall -Wno-deprecated-declarations
 | 
			
		||||
INCLUDES += -I$(COMMON_DIR) -I$(LIB_DIR)/src -I$(LIB_DIR)/include
 | 
			
		||||
BASE_FLAGS = -fPIC
 | 
			
		||||
FULL_CFLAGS = $(BASE_FLAGS) $(CFLAGS) $(DEFINES) $(WARNINGS) $(INCLUDES) \
 | 
			
		||||
  -MMD -MP $(shell pkg-config --cflags $(PKGS))
 | 
			
		||||
FULL_LDFLAGS = $(BASE_FLAGS) $(LDFLAGS)
 | 
			
		||||
LIBS = $(shell pkg-config --libs $(LINK_PKGS)) -lpthread
 | 
			
		||||
QUIET_MAKE = make --no-print-directory
 | 
			
		||||
DEBUG_FLAGS = -g
 | 
			
		||||
RELEASE_FLAGS =
 | 
			
		||||
COVERAGE_FLAGS = -g
 | 
			
		||||
 | 
			
		||||
DEBUG_LDFLAGS = $(FULL_LDFLAGS) $(DEBUG_FLAGS)
 | 
			
		||||
RELEASE_LDFLAGS = $(FULL_LDFLAGS) $(RELEASE_FLAGS)
 | 
			
		||||
COVERAGE_LDFLAGS = $(FULL_LDFLAGS) $(COVERAGE_FLAGS) --coverage
 | 
			
		||||
 | 
			
		||||
DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG
 | 
			
		||||
RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2
 | 
			
		||||
COVERAGE_CFLAGS = $(FULL_CFLAGS) $(COVERAGE_FLAGS) --coverage
 | 
			
		||||
 | 
			
		||||
DEBUG_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_debug_lib)
 | 
			
		||||
RELEASE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_release_lib)
 | 
			
		||||
COVERAGE_LIB_FILE := $(shell $(QUIET_MAKE) -C $(LIB_DIR) print_coverage_lib)
 | 
			
		||||
 | 
			
		||||
DEBUG_LIB = $(LIB_DIR)/$(DEBUG_LIB_FILE)
 | 
			
		||||
RELEASE_LIB = $(LIB_DIR)/$(RELEASE_LIB_FILE)
 | 
			
		||||
COVERAGE_LIB = $(LIB_DIR)/$(COVERAGE_LIB_FILE)
 | 
			
		||||
 | 
			
		||||
DEBUG_LIBS = $(DEBUG_LIB) $(LIBS)
 | 
			
		||||
RELEASE_LIBS = $(RELEASE_LIB) $(LIBS)
 | 
			
		||||
COVERAGE_LIBS = $(COVERAGE_LIB) $(LIBS)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Files
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
TEST_DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
TEST_RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
TEST_COVERAGE_OBJS = $(SRC:%.c=$(COVERAGE_BUILD_DIR)/%.o)
 | 
			
		||||
COMMON_DEBUG_OBJS = $(COMMON_SRC:%.c=$(COMMON_DEBUG_BUILD_DIR)/%.o)
 | 
			
		||||
COMMON_RELEASE_OBJS = $(COMMON_SRC:%.c=$(COMMON_RELEASE_BUILD_DIR)/%.o)
 | 
			
		||||
COMMON_COVERAGE_OBJS = $(COMMON_SRC:%.c=$(COMMON_COVERAGE_BUILD_DIR)/%.o)
 | 
			
		||||
DEBUG_OBJS = $(COMMON_DEBUG_OBJS) $(TEST_DEBUG_OBJS)
 | 
			
		||||
RELEASE_OBJS = $(COMMON_RELEASE_OBJS) $(TEST_RELEASE_OBJS)
 | 
			
		||||
COVERAGE_OBJS = $(COMMON_COVERAGE_OBJS) $(TEST_COVERAGE_OBJS)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Dependencies
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d)
 | 
			
		||||
ifneq ($(MAKECMDGOALS),clean)
 | 
			
		||||
ifneq ($(strip $(DEPS)),)
 | 
			
		||||
-include $(DEPS)
 | 
			
		||||
endif
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
$(DEBUG_LIB): | debug_lib
 | 
			
		||||
$(RELEASE_LIB): | release_lib
 | 
			
		||||
$(COVERAGE_LIB): | coverage_lib
 | 
			
		||||
 | 
			
		||||
$(TEST_DEBUG_OBJS): | $(DEBUG_BUILD_DIR)
 | 
			
		||||
$(TEST_RELEASE_OBJS): | $(RELEASE_BUILD_DIR)
 | 
			
		||||
$(TEST_COVERAGE_OBJS): | $(COVERAGE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
$(COMMON_DEBUG_OBJS): | $(COMMON_DEBUG_BUILD_DIR)
 | 
			
		||||
$(COMMON_RELEASE_OBJS): | $(COMMON_RELEASE_BUILD_DIR)
 | 
			
		||||
$(COMMON_COVERAGE_OBJS): | $(COMMON_COVERAGE_BUILD_DIR)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Rules
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE)
 | 
			
		||||
RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE)
 | 
			
		||||
COVERAGE_EXE = $(COVERAGE_BUILD_DIR)/$(EXE)
 | 
			
		||||
 | 
			
		||||
debug: debug_lib $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
release: release_lib $(RELEASE_EXE)
 | 
			
		||||
 | 
			
		||||
coverage: coverage_lib $(COVERAGE_EXE)
 | 
			
		||||
 | 
			
		||||
unitclean:
 | 
			
		||||
	rm -f *~
 | 
			
		||||
	rm -fr $(BUILD_DIR) $(COMMON_BUILD_DIR) 
 | 
			
		||||
 | 
			
		||||
clean: unitclean
 | 
			
		||||
 | 
			
		||||
cleaner: unitclean
 | 
			
		||||
	@make -C $(LIB_DIR) clean
 | 
			
		||||
 | 
			
		||||
test_banner:
 | 
			
		||||
	@echo "===========" $(EXE) "=========== "
 | 
			
		||||
 | 
			
		||||
test: test_banner debug 
 | 
			
		||||
	@$(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
valgrind: test_banner debug
 | 
			
		||||
	@G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --tool=memcheck --leak-check=full --show-possibly-lost=no $(DEBUG_EXE)
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(COVERAGE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_DEBUG_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_RELEASE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_COVERAGE_BUILD_DIR):
 | 
			
		||||
	mkdir -p $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(COVERAGE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_DEBUG_BUILD_DIR)/%.o : $(COMMON_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_RELEASE_BUILD_DIR)/%.o : $(COMMON_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(COMMON_COVERAGE_BUILD_DIR)/%.o : $(COMMON_DIR)/%.c
 | 
			
		||||
	$(CC) -c $(COVERAGE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@
 | 
			
		||||
 | 
			
		||||
$(DEBUG_EXE): $(DEBUG_LIB) $(DEBUG_OBJS)
 | 
			
		||||
	$(LD) $(DEBUG_LDFLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
$(RELEASE_EXE): $(RELEASE_LIB) $(RELEASE_OBJS)
 | 
			
		||||
	$(LD) $(RELEASE_LDFLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
$(COVERAGE_EXE): $(COVERAG_LIB) $(COVERAGE_OBJS)
 | 
			
		||||
	$(LD) $(COVERAGE_LDFLAGS) $(COVERAGE_OBJS) $(COVERAGE_LIBS) -o $@
 | 
			
		||||
 | 
			
		||||
debug_lib:
 | 
			
		||||
	$(MAKE) -C $(LIB_DIR) $@
 | 
			
		||||
 | 
			
		||||
release_lib:
 | 
			
		||||
	$(MAKE) -C $(LIB_DIR) $@
 | 
			
		||||
 | 
			
		||||
coverage_lib:
 | 
			
		||||
	$(MAKE) -C $(LIB_DIR) $@
 | 
			
		||||
							
								
								
									
										109
									
								
								unit/common/test_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								unit/common/test_common.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TEST_COMMON_H
 | 
			
		||||
#define TEST_COMMON_H
 | 
			
		||||
 | 
			
		||||
#include <radio_types.h>
 | 
			
		||||
 | 
			
		||||
#define TEST_FLAG_DEBUG (0x01)
 | 
			
		||||
typedef struct test_opt {
 | 
			
		||||
    int flags;
 | 
			
		||||
} TestOpt;
 | 
			
		||||
 | 
			
		||||
/* Should be invoked after g_test_init */
 | 
			
		||||
void
 | 
			
		||||
test_init(
 | 
			
		||||
    TestOpt* opt,
 | 
			
		||||
    int argc,
 | 
			
		||||
    char* argv[]);
 | 
			
		||||
 | 
			
		||||
/* Run loop with a timeout */
 | 
			
		||||
void
 | 
			
		||||
test_run(
 | 
			
		||||
    const TestOpt* opt,
 | 
			
		||||
    GMainLoop* loop);
 | 
			
		||||
 | 
			
		||||
/* Quits the event loop on the next iteration */
 | 
			
		||||
void
 | 
			
		||||
test_quit_later(
 | 
			
		||||
    GMainLoop* loop);
 | 
			
		||||
 | 
			
		||||
/* Quits the event loop after n iterations */
 | 
			
		||||
void
 | 
			
		||||
test_quit_later_n(
 | 
			
		||||
    GMainLoop* loop,
 | 
			
		||||
    guint n);
 | 
			
		||||
 | 
			
		||||
#define TEST_TIMEOUT_SEC (20)
 | 
			
		||||
#define TEST_TIMEOUT_MS (1000*TEST_TIMEOUT_SEC)
 | 
			
		||||
 | 
			
		||||
/* Helper macros */
 | 
			
		||||
 | 
			
		||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 | 
			
		||||
#  define TEST_INT16_BYTES(v) \
 | 
			
		||||
    (guint8)(v), (guint8)((v) >> 8)
 | 
			
		||||
#  define TEST_INT32_BYTES(v) \
 | 
			
		||||
    (guint8)(v), (guint8)((v) >> 8), \
 | 
			
		||||
    (guint8)((v) >> 16), (guint8)((v) >> 24)
 | 
			
		||||
#  define TEST_INT64_BYTES(v) \
 | 
			
		||||
    (guint8)(v), (guint8)((v) >> 8), \
 | 
			
		||||
    (guint8)((v) >> 16), (guint8)((v) >> 24), \
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 32), (guint8)(((guint64)(v)) >> 40), \
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 48), (guint8)(((guint64)(v)) >> 56)
 | 
			
		||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
 | 
			
		||||
#  define TEST_INT16_BYTES(v) \
 | 
			
		||||
    (guint8)((v) >> 8), (guint8)(v)
 | 
			
		||||
#  define TEST_INT32_BYTES(v) \
 | 
			
		||||
    (guint8)((v) >> 24), (guint8)((v) >> 16), \
 | 
			
		||||
    (guint8)((v) >> 8), (guint8)(v)
 | 
			
		||||
#  define TEST_INT64_BYTES(v) \
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 56), (guint8)(((guint64)(v)) >> 48), \
 | 
			
		||||
    (guint8)(((guint64)(v)) >> 40), (guint8)(((guint64)(v)) >> 32), \
 | 
			
		||||
    (guint8)((v) >> 24), (guint8)((v) >> 16), \
 | 
			
		||||
    (guint8)((v) >> 8), (guint8)(v)
 | 
			
		||||
#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
 | 
			
		||||
#error unknown ENDIAN type
 | 
			
		||||
#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
 | 
			
		||||
 | 
			
		||||
#define TEST_ARRAY_AND_COUNT(a) a, G_N_ELEMENTS(a)
 | 
			
		||||
#define TEST_ARRAY_AND_SIZE(a) a, sizeof(a)
 | 
			
		||||
 | 
			
		||||
#endif /* TEST_COMMON_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										165
									
								
								unit/common/test_gbinder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								unit/common/test_gbinder.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TEST_GBINDER_H
 | 
			
		||||
#define TEST_GBINDER_H
 | 
			
		||||
 | 
			
		||||
#include <gbinder.h>
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_data TestGBinderData;
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_reader_writer.c */
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_data_new(
 | 
			
		||||
    const char* iface);
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_data_ref(
 | 
			
		||||
    TestGBinderData* data);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_unref(
 | 
			
		||||
    TestGBinderData* data);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_add_int32(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    guint32 value);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_add_hidl_struct(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize size);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_init_reader(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    GBinderReader* reader);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_init_writer(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    GBinderWriter* writer);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_local_request.c */
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
test_gbinder_local_request_new(
 | 
			
		||||
    const char* iface);
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
test_gbinder_local_request_interface(
 | 
			
		||||
    GBinderLocalRequest* local);
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_local_request_data(
 | 
			
		||||
    GBinderLocalRequest* local);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_local_reply.c */
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
test_gbinder_local_reply_new(
 | 
			
		||||
    void);
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_local_reply_data(
 | 
			
		||||
    GBinderLocalReply* reply);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_remote_request.c */
 | 
			
		||||
 | 
			
		||||
GBinderRemoteRequest*
 | 
			
		||||
test_gbinder_remote_request_new(
 | 
			
		||||
    GBinderLocalRequest* req);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_remote_reply.c */
 | 
			
		||||
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
test_gbinder_remote_reply_new(
 | 
			
		||||
    GBinderLocalReply* reply);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_local_object.c */
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
test_gbinder_local_object_new(
 | 
			
		||||
    const char* const* ifaces,
 | 
			
		||||
    GBinderLocalTransactFunc txproc,
 | 
			
		||||
    void* user_data);
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
test_gbinder_local_object_handle_tx(
 | 
			
		||||
    GBinderLocalObject* self,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_remote_object.c */
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
test_gbinder_remote_object_new(
 | 
			
		||||
    GBinderLocalObject* local);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_remote_object_kill(
 | 
			
		||||
    GBinderRemoteObject* remote);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
test_gbinder_remote_object_dead(
 | 
			
		||||
    GBinderRemoteObject* remote);
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
test_gbinder_remote_object_to_local(
 | 
			
		||||
    GBinderRemoteObject* remote);
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_client.c */
 | 
			
		||||
 | 
			
		||||
extern int test_gbinder_client_tx_fail_count;
 | 
			
		||||
 | 
			
		||||
/* test_gbinder_servicemanager.c */
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
test_gbinder_servicemanager_new_service(
 | 
			
		||||
    GBinderServiceManager* manager,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* local);
 | 
			
		||||
 | 
			
		||||
#endif /* TEST_GBINDER_H */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										402
									
								
								unit/common/test_gbinder_client.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										402
									
								
								unit/common/test_gbinder_client.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,402 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021-2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021-2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_client_tx {
 | 
			
		||||
    GBinderClient* client;
 | 
			
		||||
    guint32 code;
 | 
			
		||||
    guint32 flags;
 | 
			
		||||
    GBinderLocalRequest* req;
 | 
			
		||||
    GBinderClientReplyFunc reply;
 | 
			
		||||
    GDestroyNotify destroy;
 | 
			
		||||
    void* user_data;
 | 
			
		||||
} TestGBinderClientTx;
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_client_iface_range {
 | 
			
		||||
    char* iface;
 | 
			
		||||
    GBytes* header;
 | 
			
		||||
    guint32 last_code;
 | 
			
		||||
} TestGBinderClientIfaceRange;
 | 
			
		||||
 | 
			
		||||
struct gbinder_client {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    GBinderRemoteObject* remote;
 | 
			
		||||
    TestGBinderClientIfaceRange* ranges;
 | 
			
		||||
    guint nr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int test_gbinder_client_tx_fail_count = 0;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_client_free(
 | 
			
		||||
    GBinderClient* self)
 | 
			
		||||
{
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < self->nr; i++) {
 | 
			
		||||
        TestGBinderClientIfaceRange* r = self->ranges + i;
 | 
			
		||||
 | 
			
		||||
        g_bytes_unref(r->header);
 | 
			
		||||
        g_free(r->iface);
 | 
			
		||||
    }
 | 
			
		||||
    g_free(self->ranges);
 | 
			
		||||
    gbinder_remote_object_unref(self->remote);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_client_init_range(
 | 
			
		||||
    TestGBinderClientIfaceRange* r,
 | 
			
		||||
    const GBinderClientIfaceInfo* info)
 | 
			
		||||
{
 | 
			
		||||
    r->header = g_bytes_new(info->iface, strlen(info->iface));
 | 
			
		||||
    r->iface = g_strdup(info->iface);
 | 
			
		||||
    r->last_code = info->last_code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
int
 | 
			
		||||
test_gbinder_client_sort_ranges(
 | 
			
		||||
    const void* p1,
 | 
			
		||||
    const void* p2)
 | 
			
		||||
{
 | 
			
		||||
    const TestGBinderClientIfaceRange* r1 = p1;
 | 
			
		||||
    const TestGBinderClientIfaceRange* r2 = p2;
 | 
			
		||||
 | 
			
		||||
    return (r1->last_code < r2->last_code) ? (-1) :
 | 
			
		||||
        (r1->last_code > r2->last_code) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
const TestGBinderClientIfaceRange*
 | 
			
		||||
test_gbinder_client_find_range(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code)
 | 
			
		||||
{
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < self->nr; i++) {
 | 
			
		||||
        const TestGBinderClientIfaceRange* r = self->ranges + i;
 | 
			
		||||
 | 
			
		||||
        if (r->last_code >= code) {
 | 
			
		||||
            return r;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
test_gbinder_client_transact(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    guint32 flags,
 | 
			
		||||
    GBinderLocalRequest* req,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalObject* obj = test_gbinder_remote_object_to_local(self->remote);
 | 
			
		||||
    GBinderRemoteRequest* remote_req = test_gbinder_remote_request_new(req);
 | 
			
		||||
    GBinderLocalReply* reply = test_gbinder_local_object_handle_tx(obj,
 | 
			
		||||
        remote_req, code, flags, status);
 | 
			
		||||
    GBinderRemoteReply* remote_reply = test_gbinder_remote_reply_new(reply);
 | 
			
		||||
 | 
			
		||||
    gbinder_remote_request_unref(remote_req);
 | 
			
		||||
    gbinder_local_reply_unref(reply);
 | 
			
		||||
    return remote_reply;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
test_gbinder_client_transact_sync(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    guint32 flags,
 | 
			
		||||
    GBinderLocalRequest* req,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    GBinderRemoteReply* reply = NULL;
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        GBinderRemoteObject* obj = self->remote;
 | 
			
		||||
 | 
			
		||||
        if (!test_gbinder_remote_object_dead(obj)) {
 | 
			
		||||
            GBinderLocalRequest* tmp = NULL;
 | 
			
		||||
 | 
			
		||||
            if (!req) {
 | 
			
		||||
                const TestGBinderClientIfaceRange* r =
 | 
			
		||||
                    test_gbinder_client_find_range(self, code);
 | 
			
		||||
 | 
			
		||||
                if (r) {
 | 
			
		||||
                    req = tmp = test_gbinder_local_request_new(r->iface);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (req) {
 | 
			
		||||
                reply = test_gbinder_client_transact(self, code, flags, req,
 | 
			
		||||
                    status);
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_local_request_unref(tmp);
 | 
			
		||||
        } else {
 | 
			
		||||
            GDEBUG("Refusing to perform transaction with a dead object");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return reply;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_gbinder_client_tx_handle(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    int status = -1;
 | 
			
		||||
    TestGBinderClientTx* tx = data;
 | 
			
		||||
    GBinderRemoteReply* reply = test_gbinder_client_transact
 | 
			
		||||
        (tx->client, tx->code, tx->flags, tx->req, &status);
 | 
			
		||||
 | 
			
		||||
    if (tx->reply) {
 | 
			
		||||
        tx->reply(tx->client, reply, status, tx->user_data);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_remote_reply_unref(reply);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_client_tx_destroy(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderClientTx* tx = data;
 | 
			
		||||
 | 
			
		||||
    if (tx->destroy) {
 | 
			
		||||
        tx->destroy(tx->user_data);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_local_request_unref(tx->req);
 | 
			
		||||
    gbinder_client_unref(tx->client);
 | 
			
		||||
    g_free(tx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderClient*
 | 
			
		||||
gbinder_client_new2(
 | 
			
		||||
    GBinderRemoteObject* remote,
 | 
			
		||||
    const GBinderClientIfaceInfo* ifaces,
 | 
			
		||||
    gsize count)
 | 
			
		||||
{
 | 
			
		||||
    if (remote) {
 | 
			
		||||
        GBinderClient* self = g_new0(GBinderClient, 1);
 | 
			
		||||
 | 
			
		||||
        g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
        self->remote = gbinder_remote_object_ref(remote);
 | 
			
		||||
        if (count > 0) {
 | 
			
		||||
            gsize i;
 | 
			
		||||
 | 
			
		||||
            self->nr = count;
 | 
			
		||||
            self->ranges = g_new(TestGBinderClientIfaceRange, self->nr);
 | 
			
		||||
            for (i = 0; i < count; i++) {
 | 
			
		||||
               test_gbinder_client_init_range(self->ranges + i, ifaces + i);
 | 
			
		||||
            }
 | 
			
		||||
            qsort(self->ranges, count, sizeof(TestGBinderClientIfaceRange),
 | 
			
		||||
                test_gbinder_client_sort_ranges);
 | 
			
		||||
        } else {
 | 
			
		||||
            /* No interface info */
 | 
			
		||||
            self->nr = 1;
 | 
			
		||||
            self->ranges = g_new0(TestGBinderClientIfaceRange, 1);
 | 
			
		||||
            self->ranges[0].last_code = UINT_MAX;
 | 
			
		||||
        }
 | 
			
		||||
        return self;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderClient*
 | 
			
		||||
gbinder_client_ref(
 | 
			
		||||
    GBinderClient* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_client_unref(
 | 
			
		||||
    GBinderClient* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_client_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBytes*
 | 
			
		||||
gbinder_client_rpc_header(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        const TestGBinderClientIfaceRange* r =
 | 
			
		||||
            test_gbinder_client_find_range(self, code);
 | 
			
		||||
 | 
			
		||||
        if (r) {
 | 
			
		||||
            return r->header;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_client_new_request2(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        const TestGBinderClientIfaceRange* r =
 | 
			
		||||
            test_gbinder_client_find_range(self, code);
 | 
			
		||||
 | 
			
		||||
        if (r) {
 | 
			
		||||
            return test_gbinder_local_request_new(r->iface);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
gbinder_client_transact_sync_reply(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    GBinderLocalRequest* req,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    return test_gbinder_client_transact_sync(self, code, 0, req, status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
gbinder_client_transact_sync_oneway(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    GBinderLocalRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    int status = -1;
 | 
			
		||||
 | 
			
		||||
    g_assert(!test_gbinder_client_transact_sync(self, code,
 | 
			
		||||
        GBINDER_TX_FLAG_ONEWAY, req, &status));
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
gbinder_client_transact(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    guint32 code,
 | 
			
		||||
    guint32 flags,
 | 
			
		||||
    GBinderLocalRequest* req,
 | 
			
		||||
    GBinderClientReplyFunc reply,
 | 
			
		||||
    GDestroyNotify destroy,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    gulong id = 0;
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        GBinderRemoteObject* obj = self->remote;
 | 
			
		||||
 | 
			
		||||
        if (!test_gbinder_remote_object_dead(obj)) {
 | 
			
		||||
            if (test_gbinder_client_tx_fail_count) {
 | 
			
		||||
                if (test_gbinder_client_tx_fail_count > 0) {
 | 
			
		||||
                    test_gbinder_client_tx_fail_count--;
 | 
			
		||||
                }
 | 
			
		||||
                GDEBUG("Simulating transaction failure");
 | 
			
		||||
            } else {
 | 
			
		||||
                GBinderLocalRequest* tmp = NULL;
 | 
			
		||||
 | 
			
		||||
                if (!req) {
 | 
			
		||||
                    const TestGBinderClientIfaceRange* r =
 | 
			
		||||
                        test_gbinder_client_find_range(self, code);
 | 
			
		||||
 | 
			
		||||
                    if (r) {
 | 
			
		||||
                        req = tmp = test_gbinder_local_request_new(r->iface);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (req) {
 | 
			
		||||
                    TestGBinderClientTx* tx = g_new0(TestGBinderClientTx, 1);
 | 
			
		||||
 | 
			
		||||
                    tx->client = gbinder_client_ref(self);
 | 
			
		||||
                    tx->code = code;
 | 
			
		||||
                    tx->flags = flags;
 | 
			
		||||
                    tx->req = gbinder_local_request_ref(req);
 | 
			
		||||
                    tx->reply = reply;
 | 
			
		||||
                    tx->destroy = destroy;
 | 
			
		||||
                    tx->user_data = user_data;
 | 
			
		||||
                    id = g_idle_add_full(G_PRIORITY_DEFAULT,
 | 
			
		||||
                        test_gbinder_client_tx_handle, tx,
 | 
			
		||||
                        test_gbinder_client_tx_destroy);
 | 
			
		||||
                }
 | 
			
		||||
                gbinder_local_request_unref(tmp);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            GDEBUG("Refusing to perform transaction with a dead object");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_client_cancel(
 | 
			
		||||
    GBinderClient* self,
 | 
			
		||||
    gulong id)
 | 
			
		||||
{
 | 
			
		||||
    if (id) {
 | 
			
		||||
        g_source_remove((guint)id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										153
									
								
								unit/common/test_gbinder_local_object.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								unit/common/test_gbinder_local_object.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_strv.h>
 | 
			
		||||
 | 
			
		||||
struct gbinder_local_object {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    char** ifaces;
 | 
			
		||||
    GBinderLocalTransactFunc txproc;
 | 
			
		||||
    void* user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char hidl_base_interface[] = "android.hidl.base@1.0::IBase";
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_local_object_free(
 | 
			
		||||
    GBinderLocalObject* self)
 | 
			
		||||
{
 | 
			
		||||
    g_strfreev(self->ifaces);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
test_gbinder_local_object_new(
 | 
			
		||||
    const char* const* ifaces,
 | 
			
		||||
    GBinderLocalTransactFunc txproc,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalObject* self = g_new0(GBinderLocalObject, 1);
 | 
			
		||||
    guint i = 0, n = gutil_strv_length((char**)ifaces);
 | 
			
		||||
    gboolean append_base_interface;
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0(gutil_strv_last((char**)ifaces), hidl_base_interface)) {
 | 
			
		||||
        append_base_interface = TRUE;
 | 
			
		||||
        n++;
 | 
			
		||||
    } else {
 | 
			
		||||
        append_base_interface = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    self->ifaces = g_new(char*, n + 1);
 | 
			
		||||
    if (ifaces) {
 | 
			
		||||
        while (*ifaces) {
 | 
			
		||||
            self->ifaces[i++] = g_strdup(*ifaces++);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (append_base_interface) {
 | 
			
		||||
        self->ifaces[i++] = g_strdup(hidl_base_interface);
 | 
			
		||||
    }
 | 
			
		||||
    self->ifaces[i] = NULL;
 | 
			
		||||
    self->txproc = txproc;
 | 
			
		||||
    self->user_data = user_data;
 | 
			
		||||
    g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
test_gbinder_local_object_handle_tx(
 | 
			
		||||
    GBinderLocalObject* self,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    return (self && self->txproc) ?
 | 
			
		||||
        self->txproc(self, req, code, flags, status, self->user_data) :
 | 
			
		||||
        NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
gbinder_local_object_ref(
 | 
			
		||||
    GBinderLocalObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_object_unref(
 | 
			
		||||
    GBinderLocalObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_local_object_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_object_drop(
 | 
			
		||||
    GBinderLocalObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        self->txproc = NULL;
 | 
			
		||||
        self->user_data = NULL;
 | 
			
		||||
        gbinder_local_object_unref(self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										118
									
								
								unit/common/test_gbinder_local_reply.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								unit/common/test_gbinder_local_reply.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
struct gbinder_local_reply {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    TestGBinderData* data;
 | 
			
		||||
    char* iface;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_local_reply_free(
 | 
			
		||||
    GBinderLocalReply* self)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_unref(self->data);
 | 
			
		||||
    g_free(self->iface);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
test_gbinder_local_reply_new(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalReply* self = g_new0(GBinderLocalReply, 1);
 | 
			
		||||
 | 
			
		||||
    g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
    self->data = test_gbinder_data_new(NULL);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_local_reply_data(
 | 
			
		||||
    GBinderLocalReply* self)
 | 
			
		||||
{
 | 
			
		||||
    return self ? self->data : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
gbinder_local_reply_ref(
 | 
			
		||||
    GBinderLocalReply* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_reply_unref(
 | 
			
		||||
    GBinderLocalReply* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_local_reply_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_reply_init_writer(
 | 
			
		||||
    GBinderLocalReply* self,
 | 
			
		||||
    GBinderWriter* writer)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_init_writer(self->data, writer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										141
									
								
								unit/common/test_gbinder_local_request.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								unit/common/test_gbinder_local_request.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
struct gbinder_local_request {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    TestGBinderData* data;
 | 
			
		||||
    char* iface;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_local_request_free(
 | 
			
		||||
    GBinderLocalRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_unref(self->data);
 | 
			
		||||
    g_free(self->iface);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
test_gbinder_local_request_new(
 | 
			
		||||
    const char* iface)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* self = g_new0(GBinderLocalRequest, 1);
 | 
			
		||||
 | 
			
		||||
    g_assert(iface);
 | 
			
		||||
    g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
    self->data = test_gbinder_data_new(iface);
 | 
			
		||||
    self->iface = g_strdup(iface);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
test_gbinder_local_request_interface(
 | 
			
		||||
    GBinderLocalRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    return self ? self->iface : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_local_request_data(
 | 
			
		||||
    GBinderLocalRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    return self ? self->data : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_local_request_ref(
 | 
			
		||||
    GBinderLocalRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_request_unref(
 | 
			
		||||
    GBinderLocalRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_local_request_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_local_request_init_writer(
 | 
			
		||||
    GBinderLocalRequest* self,
 | 
			
		||||
    GBinderWriter* writer)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_init_writer(self->data, writer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalRequest*
 | 
			
		||||
gbinder_local_request_append_int32(
 | 
			
		||||
    GBinderLocalRequest* self,
 | 
			
		||||
    guint32 value)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        GBinderWriter writer;
 | 
			
		||||
 | 
			
		||||
        test_gbinder_data_init_writer(self->data, &writer);
 | 
			
		||||
        gbinder_writer_append_int32(&writer, value);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										488
									
								
								unit/common/test_gbinder_reader_writer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								unit/common/test_gbinder_reader_writer.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,488 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_misc.h>
 | 
			
		||||
#include <gutil_idlepool.h>
 | 
			
		||||
 | 
			
		||||
typedef enum test_gbinder_data_type {
 | 
			
		||||
    DATA_TYPE_BOOLEAN,
 | 
			
		||||
    DATA_TYPE_INT32,
 | 
			
		||||
    DATA_TYPE_BUFFER,
 | 
			
		||||
    DATA_TYPE_LOCAL_OBJ
 | 
			
		||||
} DATA_TYPE;
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_data_item TestGBinderDataItem;
 | 
			
		||||
struct test_gbinder_data_item {
 | 
			
		||||
    TestGBinderDataItem* next;
 | 
			
		||||
    DATA_TYPE type;
 | 
			
		||||
    union {
 | 
			
		||||
        gboolean b;
 | 
			
		||||
        gint32 i32;
 | 
			
		||||
        struct {
 | 
			
		||||
            void* buf;
 | 
			
		||||
            gsize size;
 | 
			
		||||
        } blob;
 | 
			
		||||
        GBinderLocalObject* obj;
 | 
			
		||||
    } data;
 | 
			
		||||
    void (*destroy)(TestGBinderDataItem*);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct test_gbinder_data {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    TestGBinderDataItem* items;
 | 
			
		||||
    GUtilIdlePool* pool;
 | 
			
		||||
    char* iface;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_reader {
 | 
			
		||||
    TestGBinderDataItem* item;
 | 
			
		||||
} TestGBinderReader;
 | 
			
		||||
 | 
			
		||||
typedef struct test_gbinder_writer {
 | 
			
		||||
    TestGBinderData* data;
 | 
			
		||||
} TestGBinderWriter;
 | 
			
		||||
 | 
			
		||||
static inline TestGBinderReader* test_gbinder_reader_cast(GBinderReader* reader)
 | 
			
		||||
    { return (TestGBinderReader*)reader; }
 | 
			
		||||
 | 
			
		||||
static inline TestGBinderWriter* test_gbinder_writer_cast(GBinderWriter* writer)
 | 
			
		||||
    { return (TestGBinderWriter*)writer; }
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_item_destroy_local_obj(
 | 
			
		||||
    TestGBinderDataItem* item)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_cmpint(item->type, == ,DATA_TYPE_LOCAL_OBJ);
 | 
			
		||||
    gbinder_local_object_unref(item->data.obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_item_destroy_buffer(
 | 
			
		||||
    TestGBinderDataItem* item)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_cmpint(item->type, == ,DATA_TYPE_BUFFER);
 | 
			
		||||
    g_free(item->data.blob.buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
TestGBinderDataItem*
 | 
			
		||||
test_gbinder_data_item_new(
 | 
			
		||||
    DATA_TYPE type)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderDataItem* item = g_new0(TestGBinderDataItem, 1);
 | 
			
		||||
 | 
			
		||||
    item->type = type;
 | 
			
		||||
    return item;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_item_free(
 | 
			
		||||
    TestGBinderDataItem* item)
 | 
			
		||||
{
 | 
			
		||||
    if (item) {
 | 
			
		||||
        test_gbinder_data_item_free(item->next);
 | 
			
		||||
        if (item->destroy) {
 | 
			
		||||
            item->destroy(item);
 | 
			
		||||
        }
 | 
			
		||||
        g_free(item);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_free(
 | 
			
		||||
    TestGBinderData* data)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_item_free(data->items);
 | 
			
		||||
    gutil_idle_pool_destroy(data->pool);
 | 
			
		||||
    g_free(data->iface);
 | 
			
		||||
    g_free(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
guint
 | 
			
		||||
test_gbinder_data_count_buffers(
 | 
			
		||||
    TestGBinderData* data)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderDataItem* item;
 | 
			
		||||
    guint n;
 | 
			
		||||
 | 
			
		||||
    for (n = 0, item = data->items; item; item = item->next) {
 | 
			
		||||
        if (item->type == DATA_TYPE_BUFFER) {
 | 
			
		||||
            n++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_append(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    TestGBinderDataItem* item)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderDataItem* last = data->items;
 | 
			
		||||
 | 
			
		||||
    if (last) {
 | 
			
		||||
        while (last->next) {
 | 
			
		||||
            last = last->next;
 | 
			
		||||
        }
 | 
			
		||||
        last->next = item;
 | 
			
		||||
    } else {
 | 
			
		||||
        data->items = item;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gsize
 | 
			
		||||
test_gbinder_data_item_size(
 | 
			
		||||
    TestGBinderDataItem* item)
 | 
			
		||||
{
 | 
			
		||||
    switch (item->type) {
 | 
			
		||||
    case DATA_TYPE_BOOLEAN:
 | 
			
		||||
        return sizeof(item->data.b);
 | 
			
		||||
    case DATA_TYPE_INT32:
 | 
			
		||||
        return sizeof(item->data.i32);
 | 
			
		||||
    case DATA_TYPE_BUFFER:
 | 
			
		||||
        return sizeof(item->data.blob);
 | 
			
		||||
    case DATA_TYPE_LOCAL_OBJ:
 | 
			
		||||
        return sizeof(item->data.obj);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void*
 | 
			
		||||
test_gbinder_data_buffer(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    gsize* out_size)
 | 
			
		||||
{
 | 
			
		||||
    gsize size = 0;
 | 
			
		||||
    void* ptr = NULL;
 | 
			
		||||
 | 
			
		||||
    if (data) {
 | 
			
		||||
        TestGBinderDataItem* item;
 | 
			
		||||
        GByteArray* buf = g_byte_array_new();
 | 
			
		||||
 | 
			
		||||
        if (data->iface) {
 | 
			
		||||
            gsize header_size = strlen(data->iface);
 | 
			
		||||
 | 
			
		||||
            g_byte_array_append(buf, (void*)data->iface, header_size);
 | 
			
		||||
            size += header_size;
 | 
			
		||||
        }
 | 
			
		||||
        for (item = data->items; item; item = item->next) {
 | 
			
		||||
            gsize item_size = test_gbinder_data_item_size(item);
 | 
			
		||||
 | 
			
		||||
            g_byte_array_append(buf, (void*)&item->data, item_size);
 | 
			
		||||
            size += item_size;
 | 
			
		||||
        }
 | 
			
		||||
        ptr = g_byte_array_free(buf, FALSE);
 | 
			
		||||
    }
 | 
			
		||||
    if (out_size) *out_size = size;
 | 
			
		||||
    return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gsize
 | 
			
		||||
test_gbinder_data_size(
 | 
			
		||||
    TestGBinderData* data)
 | 
			
		||||
{
 | 
			
		||||
    gsize size = 0;
 | 
			
		||||
 | 
			
		||||
    if (data) {
 | 
			
		||||
        TestGBinderDataItem* item;
 | 
			
		||||
 | 
			
		||||
        if (data->iface) size += strlen(data->iface);
 | 
			
		||||
        for (item = data->items; item; item = item->next) {
 | 
			
		||||
            size += test_gbinder_data_item_size(item);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
guint32
 | 
			
		||||
test_gbinder_date_replace_int32(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    gsize offset,
 | 
			
		||||
    guint32 value)
 | 
			
		||||
{
 | 
			
		||||
    if (data) {
 | 
			
		||||
        gsize size = 0;
 | 
			
		||||
        TestGBinderDataItem* item;
 | 
			
		||||
 | 
			
		||||
        if (data->iface) size += strlen(data->iface);
 | 
			
		||||
        for (item = data->items; item; item = item->next) {
 | 
			
		||||
            if (size == offset) {
 | 
			
		||||
                guint32 prev;
 | 
			
		||||
 | 
			
		||||
                g_assert_cmpint(item->type, == ,DATA_TYPE_INT32);
 | 
			
		||||
                prev = item->data.i32;
 | 
			
		||||
                item->data.i32 = value;
 | 
			
		||||
                return prev;
 | 
			
		||||
            }
 | 
			
		||||
            size += test_gbinder_data_item_size(item);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_data_new(
 | 
			
		||||
    const char* iface)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderData* data = g_new0(TestGBinderData, 1);
 | 
			
		||||
 | 
			
		||||
    g_atomic_int_set(&data->refcount, 1);
 | 
			
		||||
    data->iface = g_strdup(iface); /* Doubles as a request header */
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TestGBinderData*
 | 
			
		||||
test_gbinder_data_ref(
 | 
			
		||||
    TestGBinderData* data)
 | 
			
		||||
{
 | 
			
		||||
    if (data) {
 | 
			
		||||
        g_assert_cmpint(data->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&data->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_unref(
 | 
			
		||||
    TestGBinderData* data)
 | 
			
		||||
{
 | 
			
		||||
    if (data) {
 | 
			
		||||
        g_assert_cmpint(data->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&data->refcount)) {
 | 
			
		||||
            test_gbinder_data_free(data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_init_reader(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
{
 | 
			
		||||
    memset(reader, 0, sizeof(*reader));
 | 
			
		||||
    if (data) {
 | 
			
		||||
        test_gbinder_reader_cast(reader)->item = data->items;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_data_init_writer(
 | 
			
		||||
    TestGBinderData* data,
 | 
			
		||||
    GBinderWriter* writer)
 | 
			
		||||
{
 | 
			
		||||
    if (writer) {
 | 
			
		||||
        memset(writer, 0, sizeof(*writer));
 | 
			
		||||
        if (data) {
 | 
			
		||||
            test_gbinder_writer_cast(writer)->data = data;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_uint32(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    guint32* value)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderReader* self = test_gbinder_reader_cast(reader);
 | 
			
		||||
    TestGBinderDataItem* item = self->item;
 | 
			
		||||
 | 
			
		||||
    if (item && item->type == DATA_TYPE_INT32) {
 | 
			
		||||
        if (value) {
 | 
			
		||||
            *value = item->data.i32;
 | 
			
		||||
        }
 | 
			
		||||
        self->item = item->next;
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
gbinder_reader_read_int32(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gint32* value)
 | 
			
		||||
{
 | 
			
		||||
    return gbinder_reader_read_uint32(reader, (guint32*)value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_reader_read_hidl_struct1(
 | 
			
		||||
    GBinderReader* reader,
 | 
			
		||||
    gsize size)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderReader* self = test_gbinder_reader_cast(reader);
 | 
			
		||||
    TestGBinderDataItem* item = self->item;
 | 
			
		||||
 | 
			
		||||
    if (item && item->type == DATA_TYPE_BUFFER &&
 | 
			
		||||
        item->data.blob.size == size) {
 | 
			
		||||
        self->item = item->next;
 | 
			
		||||
        return item->data.blob.buf;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_reader_read_object(
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderReader* self = test_gbinder_reader_cast(reader);
 | 
			
		||||
    TestGBinderDataItem* item = self->item;
 | 
			
		||||
 | 
			
		||||
    if (item && item->type == DATA_TYPE_LOCAL_OBJ) {
 | 
			
		||||
        self->item = item->next;
 | 
			
		||||
        return test_gbinder_remote_object_new(item->data.obj);
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void*
 | 
			
		||||
gbinder_writer_get_data(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    gsize* size)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
    TestGBinderData* data = self->data;
 | 
			
		||||
    void* buf = test_gbinder_data_buffer(data, size);
 | 
			
		||||
 | 
			
		||||
    if (buf) {
 | 
			
		||||
        if (!data->pool) {
 | 
			
		||||
            data->pool = gutil_idle_pool_new();
 | 
			
		||||
        }
 | 
			
		||||
        gutil_idle_pool_add(data->pool, buf, g_free);
 | 
			
		||||
    }
 | 
			
		||||
    return buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gsize
 | 
			
		||||
gbinder_writer_bytes_written(
 | 
			
		||||
    GBinderWriter* writer)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
 | 
			
		||||
    return test_gbinder_data_size(self->data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_int32(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    guint32 value)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
    TestGBinderDataItem* item = test_gbinder_data_item_new(DATA_TYPE_INT32);
 | 
			
		||||
 | 
			
		||||
    item->data.i32 = value;
 | 
			
		||||
    test_gbinder_data_append(self->data, item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_overwrite_int32(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    gsize offset,
 | 
			
		||||
    gint32 value)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
 | 
			
		||||
    test_gbinder_date_replace_int32(self->data, offset, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_bool(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    gboolean value)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
    TestGBinderDataItem* item = test_gbinder_data_item_new(DATA_TYPE_BOOLEAN);
 | 
			
		||||
 | 
			
		||||
    item->data.b = value;
 | 
			
		||||
    test_gbinder_data_append(self->data, item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
guint
 | 
			
		||||
gbinder_writer_append_buffer_object(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    const void* buf,
 | 
			
		||||
    gsize size)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
    TestGBinderDataItem* item = test_gbinder_data_item_new(DATA_TYPE_BUFFER);
 | 
			
		||||
    const guint index = test_gbinder_data_count_buffers(self->data);
 | 
			
		||||
 | 
			
		||||
    item->destroy = test_gbinder_data_item_destroy_buffer;
 | 
			
		||||
    item->data.blob.buf = gutil_memdup(buf, size);
 | 
			
		||||
    item->data.blob.size = size;
 | 
			
		||||
    test_gbinder_data_append(self->data, item);
 | 
			
		||||
    return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_writer_append_local_object(
 | 
			
		||||
    GBinderWriter* writer,
 | 
			
		||||
    GBinderLocalObject* obj)
 | 
			
		||||
{
 | 
			
		||||
    TestGBinderWriter* self = test_gbinder_writer_cast(writer);
 | 
			
		||||
    TestGBinderDataItem* item = test_gbinder_data_item_new(DATA_TYPE_LOCAL_OBJ);
 | 
			
		||||
 | 
			
		||||
    item->data.obj = gbinder_local_object_ref(obj);
 | 
			
		||||
    item->destroy = test_gbinder_data_item_destroy_local_obj;
 | 
			
		||||
    test_gbinder_data_append(self->data, item);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										180
									
								
								unit/common/test_gbinder_remote_object.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								unit/common/test_gbinder_remote_object.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
struct gbinder_remote_object {
 | 
			
		||||
    GObject parent;
 | 
			
		||||
    GBinderLocalObject* local;
 | 
			
		||||
    gboolean dead;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef GObjectClass GBinderRemoteObjectClass;
 | 
			
		||||
G_DEFINE_TYPE(GBinderRemoteObject, gbinder_remote_object, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
#define PARENT_CLASS gbinder_remote_object_parent_class
 | 
			
		||||
#define THIS_TYPE (gbinder_remote_object_get_type())
 | 
			
		||||
#define THIS(obj) G_TYPE_CHECK_INSTANCE_CAST(obj,THIS_TYPE,GBinderRemoteObject)
 | 
			
		||||
 | 
			
		||||
enum gbinder_remote_object_signal {
 | 
			
		||||
    SIGNAL_DEATH,
 | 
			
		||||
    SIGNAL_COUNT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SIGNAL_DEATH_NAME "death"
 | 
			
		||||
 | 
			
		||||
static guint remote_object_signals[SIGNAL_COUNT] = { 0 };
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_object_init(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_object_finalize(
 | 
			
		||||
    GObject* object)
 | 
			
		||||
{
 | 
			
		||||
    GBinderRemoteObject* self = THIS(object);
 | 
			
		||||
 | 
			
		||||
    gbinder_local_object_unref(self->local);
 | 
			
		||||
    G_OBJECT_CLASS(PARENT_CLASS)->finalize(object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_object_class_init(
 | 
			
		||||
    GBinderRemoteObjectClass* klass)
 | 
			
		||||
{
 | 
			
		||||
    G_OBJECT_CLASS(klass)->finalize = gbinder_remote_object_finalize;
 | 
			
		||||
    remote_object_signals[SIGNAL_DEATH] =
 | 
			
		||||
        g_signal_new(SIGNAL_DEATH_NAME, G_OBJECT_CLASS_TYPE(klass),
 | 
			
		||||
            G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
test_gbinder_remote_object_new(
 | 
			
		||||
    GBinderLocalObject* local)
 | 
			
		||||
{
 | 
			
		||||
    GBinderRemoteObject* self = g_object_new(THIS_TYPE, NULL);
 | 
			
		||||
 | 
			
		||||
    g_assert(local);
 | 
			
		||||
    self->local = gbinder_local_object_ref(local);
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_remote_object_kill(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self && !self->dead) {
 | 
			
		||||
        self->dead = TRUE;
 | 
			
		||||
        g_signal_emit(self, remote_object_signals[SIGNAL_DEATH], 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
test_gbinder_remote_object_dead(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
    return !self || self->dead;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
test_gbinder_remote_object_to_local(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
    return self ? self->local : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
gbinder_remote_object_ref(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_object_ref(THIS(self));
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_object_unref(
 | 
			
		||||
    GBinderRemoteObject* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_object_unref(THIS(self));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gulong
 | 
			
		||||
gbinder_remote_object_add_death_handler(
 | 
			
		||||
    GBinderRemoteObject* self,
 | 
			
		||||
    GBinderRemoteObjectNotifyFunc fn,
 | 
			
		||||
    void* data)
 | 
			
		||||
{
 | 
			
		||||
    return (self && fn) ? g_signal_connect(self, SIGNAL_DEATH_NAME,
 | 
			
		||||
        G_CALLBACK(fn), data) : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_object_remove_handler(
 | 
			
		||||
    GBinderRemoteObject* self,
 | 
			
		||||
    gulong id)
 | 
			
		||||
{
 | 
			
		||||
    if (self && id) {
 | 
			
		||||
        g_signal_handler_disconnect(self, id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Remote Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										106
									
								
								unit/common/test_gbinder_remote_reply.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								unit/common/test_gbinder_remote_reply.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
struct gbinder_remote_reply {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    TestGBinderData* data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_remote_reply_free(
 | 
			
		||||
    GBinderRemoteReply* self)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_unref(self->data);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
test_gbinder_remote_reply_new(
 | 
			
		||||
    GBinderLocalReply* reply)
 | 
			
		||||
{
 | 
			
		||||
    if (reply) {
 | 
			
		||||
        GBinderRemoteReply* self = g_new0(GBinderRemoteReply, 1);
 | 
			
		||||
        TestGBinderData* data = test_gbinder_local_reply_data(reply);
 | 
			
		||||
 | 
			
		||||
        g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
        self->data = test_gbinder_data_ref(data);
 | 
			
		||||
        return self;
 | 
			
		||||
    } else {
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteReply*
 | 
			
		||||
gbinder_remote_reply_ref(
 | 
			
		||||
    GBinderRemoteReply* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_reply_unref(
 | 
			
		||||
    GBinderRemoteReply* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_remote_reply_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										119
									
								
								unit/common/test_gbinder_remote_request.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								unit/common/test_gbinder_remote_request.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
struct gbinder_remote_request {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    TestGBinderData* data;
 | 
			
		||||
    char* iface;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_remote_request_free(
 | 
			
		||||
    GBinderRemoteRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_unref(self->data);
 | 
			
		||||
    g_free(self->iface);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteRequest*
 | 
			
		||||
test_gbinder_remote_request_new(
 | 
			
		||||
    GBinderLocalRequest* req)
 | 
			
		||||
{
 | 
			
		||||
    GBinderRemoteRequest* self = g_new0(GBinderRemoteRequest, 1);
 | 
			
		||||
 | 
			
		||||
    g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
    self->data = test_gbinder_data_ref(test_gbinder_local_request_data(req));
 | 
			
		||||
    self->iface = g_strdup(test_gbinder_local_request_interface(req));
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteRequest*
 | 
			
		||||
gbinder_remote_request_ref(
 | 
			
		||||
    GBinderRemoteRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_request_unref(
 | 
			
		||||
    GBinderRemoteRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_remote_request_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char*
 | 
			
		||||
gbinder_remote_request_interface(
 | 
			
		||||
    GBinderRemoteRequest* self)
 | 
			
		||||
{
 | 
			
		||||
    return self ? self->iface : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_remote_request_init_reader(
 | 
			
		||||
    GBinderRemoteRequest* self,
 | 
			
		||||
    GBinderReader* reader)
 | 
			
		||||
{
 | 
			
		||||
    test_gbinder_data_init_reader(self->data, reader);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										180
									
								
								unit/common/test_gbinder_servicemanager.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								unit/common/test_gbinder_servicemanager.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_idlepool.h>
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
struct gbinder_servicemanager {
 | 
			
		||||
    guint32 refcount;
 | 
			
		||||
    GHashTable* services;
 | 
			
		||||
    GUtilIdlePool* pool;
 | 
			
		||||
    char* dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GHashTable* test_servermanagers = NULL;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_gbinder_servicemanager_free(
 | 
			
		||||
    GBinderServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    /* Update the global table */
 | 
			
		||||
    g_assert(test_servermanagers);
 | 
			
		||||
    g_assert(g_hash_table_contains(test_servermanagers, self->dev));
 | 
			
		||||
    g_hash_table_remove(test_servermanagers, self->dev); /* Frees self->dev */
 | 
			
		||||
    if (g_hash_table_size(test_servermanagers) == 0) {
 | 
			
		||||
        g_hash_table_unref(test_servermanagers);
 | 
			
		||||
        test_servermanagers = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    gutil_idle_pool_destroy(self->pool);
 | 
			
		||||
    g_hash_table_destroy(self->services);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Internal API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject*
 | 
			
		||||
test_gbinder_servicemanager_new_service(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    GBinderLocalObject* local)
 | 
			
		||||
{
 | 
			
		||||
    GBinderRemoteObject* remote = test_gbinder_remote_object_new(local);
 | 
			
		||||
 | 
			
		||||
    g_hash_table_replace(self->services, g_strdup(name), remote);
 | 
			
		||||
    return gbinder_remote_object_ref(remote);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * libgbinder API
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_new(
 | 
			
		||||
    const char* dev)
 | 
			
		||||
{
 | 
			
		||||
    GBinderServiceManager* self = NULL;
 | 
			
		||||
 | 
			
		||||
    g_assert(dev && dev[0]);
 | 
			
		||||
    if (test_servermanagers) {
 | 
			
		||||
        self = g_hash_table_lookup(test_servermanagers, dev);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (self) {
 | 
			
		||||
        gbinder_servicemanager_ref(self);
 | 
			
		||||
    } else {
 | 
			
		||||
        self = g_new0(GBinderServiceManager, 1);
 | 
			
		||||
        g_atomic_int_set(&self->refcount, 1);
 | 
			
		||||
        self->pool = gutil_idle_pool_new();
 | 
			
		||||
        self->dev = g_strdup(dev);  /* Owned by test_servermanagers */
 | 
			
		||||
        self->services = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
 | 
			
		||||
            (GDestroyNotify) gbinder_remote_object_unref);
 | 
			
		||||
 | 
			
		||||
        /* Update the global table */
 | 
			
		||||
        if (!test_servermanagers) {
 | 
			
		||||
            test_servermanagers = g_hash_table_new_full(g_str_hash, g_str_equal,
 | 
			
		||||
                g_free, NULL);
 | 
			
		||||
        }
 | 
			
		||||
        g_hash_table_replace(test_servermanagers, self->dev, self);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderServiceManager*
 | 
			
		||||
gbinder_servicemanager_ref(
 | 
			
		||||
    GBinderServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        g_atomic_int_inc(&self->refcount);
 | 
			
		||||
    }
 | 
			
		||||
    return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gbinder_servicemanager_unref(
 | 
			
		||||
    GBinderServiceManager* self)
 | 
			
		||||
{
 | 
			
		||||
    if (self) {
 | 
			
		||||
        g_assert_cmpint(self->refcount, > ,0);
 | 
			
		||||
        if (g_atomic_int_dec_and_test(&self->refcount)) {
 | 
			
		||||
            test_gbinder_servicemanager_free(self);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderRemoteObject* /* autoreleased */
 | 
			
		||||
gbinder_servicemanager_get_service_sync(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* name,
 | 
			
		||||
    int* status)
 | 
			
		||||
{
 | 
			
		||||
    if (self && name) {
 | 
			
		||||
        GBinderRemoteObject* obj = g_hash_table_lookup(self->services, name);
 | 
			
		||||
 | 
			
		||||
        if (obj) {
 | 
			
		||||
            gutil_idle_pool_add(self->pool, gbinder_remote_object_ref(obj),
 | 
			
		||||
                (GDestroyNotify) gbinder_remote_object_unref);
 | 
			
		||||
            return obj;
 | 
			
		||||
        } else {
 | 
			
		||||
            GDEBUG("Name %s not found", name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GBinderLocalObject*
 | 
			
		||||
gbinder_servicemanager_new_local_object2(
 | 
			
		||||
    GBinderServiceManager* self,
 | 
			
		||||
    const char* const* ifaces,
 | 
			
		||||
    GBinderLocalTransactFunc fn,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    return self ? test_gbinder_local_object_new(ifaces, fn, user_data) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										166
									
								
								unit/common/test_main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								unit/common/test_main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2018-2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2018-2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
typedef struct test_quit_later_data{
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    guint n;
 | 
			
		||||
} TestQuitLaterData;
 | 
			
		||||
 | 
			
		||||
typedef struct test_context_data{
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    GTestFunc func;
 | 
			
		||||
} TestContextData;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_timeout_expired(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!"TIMEOUT");
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_quit_later_n_free(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestQuitLaterData* data = user_data;
 | 
			
		||||
 | 
			
		||||
    g_main_loop_unref(data->loop);
 | 
			
		||||
    g_free(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_quit_later_n_func(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestQuitLaterData* data = user_data;
 | 
			
		||||
 | 
			
		||||
    if (data->n > 0) {
 | 
			
		||||
        data->n--;
 | 
			
		||||
        return G_SOURCE_CONTINUE;
 | 
			
		||||
    } else {
 | 
			
		||||
        g_main_loop_quit(data->loop);
 | 
			
		||||
        return G_SOURCE_REMOVE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_quit_later_n(
 | 
			
		||||
    GMainLoop* loop,
 | 
			
		||||
    guint n)
 | 
			
		||||
{
 | 
			
		||||
    TestQuitLaterData* data = g_new0(TestQuitLaterData, 1);
 | 
			
		||||
 | 
			
		||||
    data->loop = g_main_loop_ref(loop);
 | 
			
		||||
    data->n = n;
 | 
			
		||||
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, test_quit_later_n_func, data,
 | 
			
		||||
        test_quit_later_n_free);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
gboolean
 | 
			
		||||
test_quit_later_cb(
 | 
			
		||||
    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
    g_main_loop_quit((GMainLoop*)data);
 | 
			
		||||
    return G_SOURCE_REMOVE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_quit_later(
 | 
			
		||||
    GMainLoop* loop)
 | 
			
		||||
{
 | 
			
		||||
    g_idle_add(test_quit_later_cb, loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_run(
 | 
			
		||||
    const TestOpt* opt,
 | 
			
		||||
    GMainLoop* loop)
 | 
			
		||||
{
 | 
			
		||||
    if (opt->flags & TEST_FLAG_DEBUG) {
 | 
			
		||||
        g_main_loop_run(loop);
 | 
			
		||||
    } else {
 | 
			
		||||
        const guint timeout_id = g_timeout_add_seconds(TEST_TIMEOUT_SEC,
 | 
			
		||||
            test_timeout_expired, NULL);
 | 
			
		||||
        g_main_loop_run(loop);
 | 
			
		||||
        g_source_remove(timeout_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
test_init(
 | 
			
		||||
    TestOpt* opt,
 | 
			
		||||
    int argc,
 | 
			
		||||
    char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    const char* sep1;
 | 
			
		||||
    const char* sep2;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    memset(opt, 0, sizeof(*opt));
 | 
			
		||||
    for (i=1; i<argc; i++) {
 | 
			
		||||
        const char* arg = argv[i];
 | 
			
		||||
        if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
 | 
			
		||||
            opt->flags |= TEST_FLAG_DEBUG;
 | 
			
		||||
        } else if (!strcmp(arg, "-v")) {
 | 
			
		||||
            GTestConfig* config = (GTestConfig*)g_test_config_vars;
 | 
			
		||||
            config->test_verbose = TRUE;
 | 
			
		||||
        } else {
 | 
			
		||||
            GWARN("Unsupported command line option %s", arg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Setup logging */
 | 
			
		||||
    sep1 = strrchr(argv[0], '/');
 | 
			
		||||
    sep2 = strrchr(argv[0], '\\');
 | 
			
		||||
    gutil_log_default.name = (sep1 && sep2) ? (MAX(sep1, sep2) + 1) :
 | 
			
		||||
        sep1 ? (sep1 + 1) : sep2 ? (sep2 + 1) : argv[0];
 | 
			
		||||
    gutil_log_default.level = g_test_verbose() ?
 | 
			
		||||
        GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
 | 
			
		||||
    gutil_log_timestamp = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										56
									
								
								unit/coverage/run
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										56
									
								
								unit/coverage/run
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
#
 | 
			
		||||
# This script requires lcov, dirname
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
TESTS="\
 | 
			
		||||
unit_client \
 | 
			
		||||
unit_config \
 | 
			
		||||
unit_instance \
 | 
			
		||||
unit_registry \
 | 
			
		||||
unit_util"
 | 
			
		||||
 | 
			
		||||
function err() {
 | 
			
		||||
    echo "*** ERROR!" $1
 | 
			
		||||
    exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check the required tools
 | 
			
		||||
which lcov >> /dev/null || err "Please install lcov"
 | 
			
		||||
which dirname >> /dev/null || err "Please install dirname"
 | 
			
		||||
 | 
			
		||||
# LCOV 1.10 has branch coverage disabled per default
 | 
			
		||||
# Previous versions didn't have the --rc option
 | 
			
		||||
if  [ ! -z "$(lcov --help | grep ' --rc ')" ] ; then
 | 
			
		||||
    LCOV_OPT="--rc lcov_branch_coverage=1"
 | 
			
		||||
    GENHTML_OPT="--branch-coverage"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
pushd `dirname $0` > /dev/null
 | 
			
		||||
COV_DIR="$PWD"
 | 
			
		||||
pushd .. > /dev/null
 | 
			
		||||
TEST_DIR="$PWD"
 | 
			
		||||
pushd .. > /dev/null
 | 
			
		||||
TOP_DIR="$PWD"
 | 
			
		||||
popd > /dev/null
 | 
			
		||||
popd > /dev/null
 | 
			
		||||
popd > /dev/null
 | 
			
		||||
 | 
			
		||||
make -C "$TOP_DIR" clean
 | 
			
		||||
for t in $TESTS ; do
 | 
			
		||||
    pushd "$TEST_DIR/$t"
 | 
			
		||||
    make -C "$TEST_DIR/$t" clean coverage || exit 1
 | 
			
		||||
    build/coverage/$t || exit 1
 | 
			
		||||
    popd
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Sometimes you need this, sometimes that :S
 | 
			
		||||
BASE_DIR="$TOP_DIR"
 | 
			
		||||
#BASE_DIR="$TOP_DIR/src"
 | 
			
		||||
 | 
			
		||||
FULL_COV="$COV_DIR/full.gcov"
 | 
			
		||||
LIB_COV="$COV_DIR/lib.gcov"
 | 
			
		||||
rm -f "$FULL_COV" "$LIB_COV"
 | 
			
		||||
lcov $LCOV_OPT -c -d "$TOP_DIR/build/coverage" -b "$BASE_DIR" -o "$FULL_COV" || exit 1
 | 
			
		||||
lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/*" -o "$LIB_COV" || exit 1
 | 
			
		||||
genhtml $GENHTML_OPT "$LIB_COV" -t "libgbinder-radio" --output-directory "$COV_DIR/report" || exit 1
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_client/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_client/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_client
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										2106
									
								
								unit/unit_client/unit_client.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2106
									
								
								unit/unit_client/unit_client.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								unit/unit_config/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_config/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_config
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										918
									
								
								unit/unit_config/unit_config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										918
									
								
								unit/unit_config/unit_config.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,918 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "test_gbinder.h"
 | 
			
		||||
 | 
			
		||||
#include "radio_config.h"
 | 
			
		||||
#include "radio_request_p.h"
 | 
			
		||||
 | 
			
		||||
#include <gutil_strv.h>
 | 
			
		||||
#include <gutil_log.h>
 | 
			
		||||
 | 
			
		||||
#define DEV GBINDER_DEFAULT_HWBINDER
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
static const GBinderClientIfaceInfo radio_config_ind_iface_info[] = {
 | 
			
		||||
    {RADIO_CONFIG_INDICATION_1_0, RADIO_CONFIG_1_0_IND_LAST }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const GBinderClientIfaceInfo radio_config_resp_iface_info[] = {
 | 
			
		||||
    {RADIO_CONFIG_RESPONSE_1_2, RADIO_CONFIG_1_2_RESP_LAST },
 | 
			
		||||
    {RADIO_CONFIG_RESPONSE_1_1, RADIO_CONFIG_1_1_RESP_LAST },
 | 
			
		||||
    {RADIO_CONFIG_RESPONSE_1_0, RADIO_CONFIG_1_0_RESP_LAST }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char* const radio_config_req_ifaces[] = {
 | 
			
		||||
    RADIO_CONFIG_1_2,
 | 
			
		||||
    RADIO_CONFIG_1_1,
 | 
			
		||||
    RADIO_CONFIG_1_0,
 | 
			
		||||
    NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char* const radio_config_fqnames[] = {
 | 
			
		||||
    RADIO_CONFIG_1_0_FQNAME,
 | 
			
		||||
    RADIO_CONFIG_1_1_FQNAME,
 | 
			
		||||
    RADIO_CONFIG_1_2_FQNAME
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_complete_not_reached(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_CONFIG_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_destroy_once(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    gboolean* destroyed = user_data;
 | 
			
		||||
 | 
			
		||||
    g_assert(!*destroyed);
 | 
			
		||||
    *destroyed = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_ind_not_reached(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_inc_cb(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    (*((int*)user_data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_config_inc_cb(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    (*((int*)user_data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
RADIO_CONFIG_RESP
 | 
			
		||||
test_config_req_resp(
 | 
			
		||||
    RADIO_CONFIG_REQ req)
 | 
			
		||||
{
 | 
			
		||||
    switch (req) {
 | 
			
		||||
#define REQ_RESP_(req,resp,Name,NAME) \
 | 
			
		||||
    case RADIO_CONFIG_REQ_##NAME: return RADIO_CONFIG_RESP_##NAME;
 | 
			
		||||
    RADIO_CONFIG_CALL_1_0(REQ_RESP_)
 | 
			
		||||
    RADIO_CONFIG_CALL_1_1(REQ_RESP_)
 | 
			
		||||
#undef REQ_RESP_
 | 
			
		||||
    case RADIO_CONFIG_REQ_SET_RESPONSE_FUNCTIONS:
 | 
			
		||||
        return RADIO_CONFIG_RESP_NONE;
 | 
			
		||||
    case RADIO_CONFIG_REQ_ANY:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    g_assert_not_reached();
 | 
			
		||||
    return RADIO_CONFIG_RESP_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Test IRadioConfig service
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_config_service {
 | 
			
		||||
    GBinderLocalObject* obj;
 | 
			
		||||
    GBinderClient* resp_client;
 | 
			
		||||
    GBinderClient* ind_client;
 | 
			
		||||
    GHashTable* req_count;
 | 
			
		||||
} TestConfigService;
 | 
			
		||||
 | 
			
		||||
#define FAIL_REQ RADIO_CONFIG_REQ_GET_PHONE_CAPABILITY
 | 
			
		||||
#define ERROR_REQ RADIO_CONFIG_REQ_SET_SIM_SLOTS_MAPPING
 | 
			
		||||
#define ERROR_RESP RADIO_CONFIG_RESP_SET_SIM_SLOTS_MAPPING
 | 
			
		||||
#define IGNORE_REQ RADIO_CONFIG_REQ_SET_MODEMS_CONFIG
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
int
 | 
			
		||||
test_config_service_req_count(
 | 
			
		||||
    TestConfigService* service,
 | 
			
		||||
    RADIO_CONFIG_REQ req)
 | 
			
		||||
{
 | 
			
		||||
    return GPOINTER_TO_INT(g_hash_table_lookup(service->req_count,
 | 
			
		||||
        GINT_TO_POINTER(req)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
GBinderLocalReply*
 | 
			
		||||
test_config_service_txproc(
 | 
			
		||||
    GBinderLocalObject* obj,
 | 
			
		||||
    GBinderRemoteRequest* req,
 | 
			
		||||
    guint code,
 | 
			
		||||
    guint flags,
 | 
			
		||||
    int* status,
 | 
			
		||||
    void* user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestConfigService* service = user_data;
 | 
			
		||||
    const char* iface = gbinder_remote_request_interface(req);
 | 
			
		||||
 | 
			
		||||
    if (gutil_strv_contains((const GStrV*)radio_config_req_ifaces, iface)) {
 | 
			
		||||
        const int count = test_config_service_req_count(service, code) + 1;
 | 
			
		||||
        GBinderReader reader;
 | 
			
		||||
 | 
			
		||||
        GDEBUG("%s %s %d", iface, radio_config_req_name(NULL, code), count);
 | 
			
		||||
        g_hash_table_insert(service->req_count, GINT_TO_POINTER(code),
 | 
			
		||||
            GINT_TO_POINTER(count));
 | 
			
		||||
 | 
			
		||||
        gbinder_remote_request_init_reader(req, &reader);
 | 
			
		||||
        if (code == RADIO_CONFIG_REQ_SET_RESPONSE_FUNCTIONS) {
 | 
			
		||||
            GBinderRemoteObject* resp_obj = gbinder_reader_read_object(&reader);
 | 
			
		||||
            GBinderRemoteObject* ind_obj = gbinder_reader_read_object(&reader);
 | 
			
		||||
 | 
			
		||||
            g_assert(resp_obj);
 | 
			
		||||
            g_assert(ind_obj);
 | 
			
		||||
            gbinder_client_unref(service->resp_client);
 | 
			
		||||
            gbinder_client_unref(service->ind_client);
 | 
			
		||||
            service->resp_client = gbinder_client_new2(resp_obj,
 | 
			
		||||
                TEST_ARRAY_AND_COUNT(radio_config_resp_iface_info));
 | 
			
		||||
            service->ind_client = gbinder_client_new2(ind_obj,
 | 
			
		||||
                TEST_ARRAY_AND_COUNT(radio_config_ind_iface_info));
 | 
			
		||||
            gbinder_remote_object_unref(resp_obj);
 | 
			
		||||
            gbinder_remote_object_unref(ind_obj);
 | 
			
		||||
        } else if (code == FAIL_REQ) {
 | 
			
		||||
            GDEBUG("failing request transaction");
 | 
			
		||||
            *status = GBINDER_STATUS_FAILED;
 | 
			
		||||
            return NULL;
 | 
			
		||||
        } else if (code == IGNORE_REQ) {
 | 
			
		||||
            GDEBUG("ignoring request transaction");
 | 
			
		||||
        } else {
 | 
			
		||||
            RadioResponseInfo info;
 | 
			
		||||
            GBinderWriter writer;
 | 
			
		||||
            RADIO_CONFIG_RESP resp_code = test_config_req_resp(code);
 | 
			
		||||
            GBinderLocalRequest* resp = gbinder_client_new_request2
 | 
			
		||||
                (service->resp_client, resp_code);
 | 
			
		||||
 | 
			
		||||
            memset(&info, 0, sizeof(info));
 | 
			
		||||
            info.type = RADIO_RESP_SOLICITED;
 | 
			
		||||
            info.error = (code == ERROR_REQ) ?
 | 
			
		||||
                RADIO_ERROR_GENERIC_FAILURE :
 | 
			
		||||
                RADIO_ERROR_NONE;
 | 
			
		||||
            g_assert(gbinder_reader_read_uint32(&reader, &info.serial));
 | 
			
		||||
            GDEBUG("serial %08x", info.serial);
 | 
			
		||||
 | 
			
		||||
            g_assert(resp);
 | 
			
		||||
            gbinder_local_request_init_writer(resp, &writer);
 | 
			
		||||
            gbinder_writer_append_buffer_object(&writer, &info, sizeof(info));
 | 
			
		||||
 | 
			
		||||
            switch (code) {
 | 
			
		||||
            case RADIO_CONFIG_REQ_SET_PREFERRED_DATA_MODEM:
 | 
			
		||||
                g_assert(gbinder_client_transact(service->resp_client,
 | 
			
		||||
                    resp_code, GBINDER_TX_FLAG_ONEWAY, resp, NULL, NULL, NULL));
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                /* No expecting anything else */
 | 
			
		||||
                g_assert_not_reached();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            gbinder_local_request_unref(resp);
 | 
			
		||||
        }
 | 
			
		||||
        *status = GBINDER_STATUS_OK;
 | 
			
		||||
        return NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
        GDEBUG("%s %u", iface, code);
 | 
			
		||||
        *status = GBINDER_STATUS_FAILED;
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_config_service_init(
 | 
			
		||||
    TestConfigService* service)
 | 
			
		||||
{
 | 
			
		||||
    memset(service, 0, sizeof(*service));
 | 
			
		||||
    service->obj = test_gbinder_local_object_new(NULL,
 | 
			
		||||
        test_config_service_txproc, service);
 | 
			
		||||
    service->req_count = g_hash_table_new(g_direct_hash, g_direct_equal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_config_service_cleanup(
 | 
			
		||||
    TestConfigService* service)
 | 
			
		||||
{
 | 
			
		||||
    g_hash_table_destroy(service->req_count);
 | 
			
		||||
    gbinder_client_unref(service->resp_client);
 | 
			
		||||
    gbinder_client_unref(service->ind_client);
 | 
			
		||||
    gbinder_local_object_unref(service->obj);
 | 
			
		||||
    memset(service, 0, sizeof(*service));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common setup for all tests
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_common {
 | 
			
		||||
    TestConfigService service;
 | 
			
		||||
    GBinderServiceManager* sm;
 | 
			
		||||
    GBinderRemoteObject* remote[RADIO_CONFIG_INTERFACE_COUNT];
 | 
			
		||||
    RadioConfig* client;
 | 
			
		||||
} TestCommon;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
RadioConfig*
 | 
			
		||||
test_common_init(
 | 
			
		||||
    TestCommon* test,
 | 
			
		||||
    RADIO_CONFIG_INTERFACE version)
 | 
			
		||||
{
 | 
			
		||||
    RADIO_CONFIG_INTERFACE v;
 | 
			
		||||
 | 
			
		||||
    memset(test, 0, sizeof(*test));
 | 
			
		||||
    test->sm = gbinder_servicemanager_new(DEV);
 | 
			
		||||
    test_config_service_init(&test->service);
 | 
			
		||||
    for (v = RADIO_CONFIG_INTERFACE_1_0; v <= version; v++) {
 | 
			
		||||
        test->remote[v] = test_gbinder_servicemanager_new_service(test->sm,
 | 
			
		||||
            radio_config_fqnames[v], test->service.obj);
 | 
			
		||||
    }
 | 
			
		||||
    test->client = radio_config_new();
 | 
			
		||||
    g_assert(test->client);
 | 
			
		||||
    return test->client;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_common_cleanup(
 | 
			
		||||
    TestCommon* test)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    radio_config_unref(test->client);
 | 
			
		||||
    test_config_service_cleanup(&test->service);
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(test->remote); i++) {
 | 
			
		||||
        gbinder_remote_object_unref(test->remote[i]);
 | 
			
		||||
    }
 | 
			
		||||
    gbinder_servicemanager_unref(test->sm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Another common setup
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_simple_data {
 | 
			
		||||
    TestCommon common;
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    int completed; /* Typically used as a boolean */
 | 
			
		||||
    int destroyed; /* Typically used as a boolean */
 | 
			
		||||
} TestSimple;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
RadioConfig*
 | 
			
		||||
test_simple_init(
 | 
			
		||||
    TestSimple* test)
 | 
			
		||||
{
 | 
			
		||||
    memset(test, 0, sizeof(*test));
 | 
			
		||||
    test->loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    return test_common_init(&test->common, RADIO_CONFIG_INTERFACE_1_1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_simple_cleanup(
 | 
			
		||||
    TestSimple* test)
 | 
			
		||||
{
 | 
			
		||||
    g_main_loop_unref(test->loop);
 | 
			
		||||
    test_common_cleanup(&test->common);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_simple_destroy_cb(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple* test = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("done");
 | 
			
		||||
    g_assert(test->completed);
 | 
			
		||||
    g_assert(!test->destroyed);
 | 
			
		||||
    test->destroyed = TRUE;
 | 
			
		||||
    test_quit_later(test->loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!radio_config_ref(NULL));
 | 
			
		||||
    g_assert(radio_config_dead(NULL));
 | 
			
		||||
    g_assert_cmpint(radio_config_interface(NULL),==,RADIO_CONFIG_INTERFACE_NONE);
 | 
			
		||||
    g_assert(!radio_config_rpc_header_size(NULL, RADIO_CONFIG_REQ_NONE));
 | 
			
		||||
    g_assert(!radio_config_req_name(NULL, RADIO_CONFIG_REQ_NONE));
 | 
			
		||||
    g_assert(!radio_config_resp_name(NULL, RADIO_CONFIG_RESP_NONE));
 | 
			
		||||
    g_assert(!radio_config_ind_name(NULL, RADIO_CONFIG_IND_NONE));
 | 
			
		||||
    g_assert(!radio_config_add_death_handler(NULL, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_request_observer(NULL,
 | 
			
		||||
        RADIO_CONFIG_REQ_ANY, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_request_observer_with_priority(NULL,
 | 
			
		||||
        RADIO_CONFIG_REQ_ANY, RADIO_OBSERVER_PRIORITY_LOWEST, NULL, NULL));
 | 
			
		||||
    radio_config_unref(NULL);
 | 
			
		||||
    g_assert(!radio_config_add_response_observer(NULL,
 | 
			
		||||
        RADIO_CONFIG_RESP_ANY, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_response_observer_with_priority(NULL,
 | 
			
		||||
        RADIO_CONFIG_RESP_ANY, RADIO_OBSERVER_PRIORITY_LOWEST, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_indication_observer(NULL,
 | 
			
		||||
        RADIO_CONFIG_IND_ANY, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_indication_observer_with_priority(NULL,
 | 
			
		||||
        RADIO_CONFIG_IND_ANY, RADIO_OBSERVER_PRIORITY_LOWEST, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_request_new(NULL, ERROR_REQ, NULL, NULL, NULL, NULL));
 | 
			
		||||
 | 
			
		||||
    radio_config_unref(NULL);
 | 
			
		||||
    radio_config_remove_handler(NULL, 0);
 | 
			
		||||
    radio_config_remove_handlers(NULL, NULL, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * name
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_name(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestCommon test;
 | 
			
		||||
    RadioConfig* client = test_common_init(&test, RADIO_CONFIG_INTERFACE_1_1);
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpstr(radio_config_req_name(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_SET_RESPONSE_FUNCTIONS), == ,
 | 
			
		||||
        "setResponseFunctions");
 | 
			
		||||
    g_assert_cmpstr(radio_config_req_name(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_SIM_SLOTS_STATUS), == ,
 | 
			
		||||
        "getSimSlotsStatus");
 | 
			
		||||
    g_assert_cmpstr(radio_config_req_name(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_PHONE_CAPABILITY), == ,
 | 
			
		||||
        "getPhoneCapability");
 | 
			
		||||
    g_assert_cmpstr(radio_config_req_name(client,
 | 
			
		||||
        (RADIO_CONFIG_REQ)123), == ,
 | 
			
		||||
        "123");
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpstr(radio_config_resp_name(client,
 | 
			
		||||
        RADIO_CONFIG_RESP_GET_SIM_SLOTS_STATUS), == ,
 | 
			
		||||
        "getSimSlotsStatusResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_config_resp_name(client,
 | 
			
		||||
        RADIO_CONFIG_RESP_GET_PHONE_CAPABILITY), == ,
 | 
			
		||||
        "getPhoneCapabilityResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_config_resp_name(client,
 | 
			
		||||
        (RADIO_CONFIG_RESP)1234), == ,
 | 
			
		||||
        "1234");
 | 
			
		||||
 | 
			
		||||
    g_assert_cmpstr(radio_config_ind_name(client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED), == ,
 | 
			
		||||
        "simSlotsStatusChanged");
 | 
			
		||||
    g_assert_cmpstr(radio_config_ind_name(client,
 | 
			
		||||
        (RADIO_CONFIG_IND)12345), == ,
 | 
			
		||||
        "12345");
 | 
			
		||||
 | 
			
		||||
    test_common_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * none
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_none(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    /* No service => no client */
 | 
			
		||||
    g_assert(!radio_config_new());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * basic
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestCommon test;
 | 
			
		||||
    RADIO_CONFIG_INTERFACE version = RADIO_CONFIG_INTERFACE_1_0;
 | 
			
		||||
    RadioConfig* client = test_common_init(&test, version);
 | 
			
		||||
    RadioRequest* req;
 | 
			
		||||
    int destroyed = 0;
 | 
			
		||||
 | 
			
		||||
    g_assert(!radio_config_dead(client));
 | 
			
		||||
    g_assert(radio_config_rpc_header_size(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_SIM_SLOTS_STATUS));
 | 
			
		||||
    g_assert_cmpint(radio_config_interface(client), == ,version);
 | 
			
		||||
    g_assert(radio_config_ref(client) == client);
 | 
			
		||||
    radio_config_unref(client);
 | 
			
		||||
 | 
			
		||||
    /* Instances are reused */
 | 
			
		||||
    g_assert(radio_config_new() == client);
 | 
			
		||||
    radio_config_unref(client);
 | 
			
		||||
    g_assert(radio_config_new_with_version(version) == client);
 | 
			
		||||
    radio_config_unref(client);
 | 
			
		||||
    g_assert(radio_config_new_with_version(RADIO_CONFIG_INTERFACE_COUNT) ==
 | 
			
		||||
        client);
 | 
			
		||||
    radio_config_unref(client);
 | 
			
		||||
 | 
			
		||||
    /* Adding NULL observer is a nop */
 | 
			
		||||
    g_assert(!radio_config_add_death_handler(client, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_request_observer(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_ANY, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_response_observer(client,
 | 
			
		||||
        RADIO_CONFIG_RESP_ANY, NULL, NULL));
 | 
			
		||||
    g_assert(!radio_config_add_indication_observer(client,
 | 
			
		||||
        RADIO_CONFIG_IND_ANY, NULL, NULL));
 | 
			
		||||
 | 
			
		||||
    /* Zero handler id is tolerated */
 | 
			
		||||
    radio_config_remove_handler(client, 0);
 | 
			
		||||
 | 
			
		||||
    /* Create and destroy the request */
 | 
			
		||||
    req = radio_config_request_new(client, RADIO_CONFIG_REQ_GET_MODEMS_CONFIG,
 | 
			
		||||
        NULL, NULL, test_inc_cb, &destroyed);
 | 
			
		||||
    g_assert(req);
 | 
			
		||||
    radio_request_unref(req);
 | 
			
		||||
    g_assert(destroyed);
 | 
			
		||||
 | 
			
		||||
    test_common_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * ind
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
typedef struct test_ind_data {
 | 
			
		||||
    TestCommon common;
 | 
			
		||||
    GMainLoop* loop;
 | 
			
		||||
    RADIO_CONFIG_IND ind;
 | 
			
		||||
} TestInd;
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_ind_cb(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestInd* test = user_data;
 | 
			
		||||
 | 
			
		||||
    /* This one is invoked first */
 | 
			
		||||
    GDEBUG("first indication  %d", code);
 | 
			
		||||
    g_assert_cmpint(code, == ,RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    g_assert_cmpint(test->ind, == ,RADIO_CONFIG_IND_NONE);
 | 
			
		||||
    test->ind = code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_ind_cb2(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_IND code,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestInd* test = user_data;
 | 
			
		||||
 | 
			
		||||
    /* This one is invoked second */
 | 
			
		||||
    GDEBUG("second indication %d", code);
 | 
			
		||||
    g_assert_cmpint(test->ind, == ,RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    g_assert_cmpint(code, == ,RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    test_quit_later(test->loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_ind(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    GBinderLocalRequest* req;
 | 
			
		||||
    GBinderClient* ind_client;
 | 
			
		||||
    RadioConfig* client;
 | 
			
		||||
    TestInd test;
 | 
			
		||||
    gulong id[2];
 | 
			
		||||
 | 
			
		||||
    memset(&test, 0, sizeof(test));
 | 
			
		||||
    test.loop = g_main_loop_new(NULL, FALSE);
 | 
			
		||||
    client = test_common_init(&test.common, RADIO_CONFIG_INTERFACE_1_1);
 | 
			
		||||
    ind_client = test.common.service.ind_client;
 | 
			
		||||
 | 
			
		||||
    /* Register and unregister one listener */
 | 
			
		||||
    id[0] = radio_config_add_indication_observer(client, RADIO_CONFIG_IND_ANY,
 | 
			
		||||
        test_ind_not_reached, NULL);
 | 
			
		||||
    radio_config_remove_handler(client, id[0]);
 | 
			
		||||
 | 
			
		||||
    /* Register actual listeners */
 | 
			
		||||
    id[0] = radio_config_add_indication_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_HIGHEST,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED,
 | 
			
		||||
        test_ind_cb, &test);
 | 
			
		||||
    id[1] = radio_config_add_indication_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_DEFAULT,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED,
 | 
			
		||||
        test_ind_cb2, &test);
 | 
			
		||||
 | 
			
		||||
    /* This one will be ignored because type is missing */
 | 
			
		||||
    req = gbinder_client_new_request2(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    g_assert_cmpint(gbinder_client_transact(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED, GBINDER_TX_FLAG_ONEWAY,
 | 
			
		||||
        req, NULL, NULL, NULL), != ,0);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* This one will be ignored because RADIO_IND_ACK_EXP is not expected */
 | 
			
		||||
    req = gbinder_client_new_request2(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    gbinder_local_request_append_int32(req, RADIO_IND_ACK_EXP);
 | 
			
		||||
    g_assert_cmpint(gbinder_client_transact(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED, GBINDER_TX_FLAG_ONEWAY,
 | 
			
		||||
        req, NULL, NULL, NULL), != ,0);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* And this one will be handled */
 | 
			
		||||
    req = gbinder_client_new_request2(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
    gbinder_local_request_append_int32(req, RADIO_IND_UNSOLICITED);
 | 
			
		||||
    /*
 | 
			
		||||
     * RadioIndicationType should be followed by vec<SimSlotStatus> but
 | 
			
		||||
     * that's not required for the purposes of this unit test.
 | 
			
		||||
     */
 | 
			
		||||
    g_assert_cmpint(gbinder_client_transact(ind_client,
 | 
			
		||||
        RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED, GBINDER_TX_FLAG_ONEWAY,
 | 
			
		||||
        req, NULL, NULL, NULL), != ,0);
 | 
			
		||||
    gbinder_local_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* And wait for test_ind_cb2 to terminate the loop */
 | 
			
		||||
    test_run(&test_opt, test.loop);
 | 
			
		||||
    g_assert_cmpint(test.ind, == ,RADIO_CONFIG_IND_SIM_SLOTS_STATUS_CHANGED);
 | 
			
		||||
 | 
			
		||||
    /* Cleanup */
 | 
			
		||||
    radio_config_remove_all_handlers(client, id);
 | 
			
		||||
    g_main_loop_unref(test.loop);
 | 
			
		||||
    test_common_cleanup(&test.common);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * resp
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_observe_req1(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    int* observed = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("high prio observed req %d", code);
 | 
			
		||||
    g_assert(!*observed);
 | 
			
		||||
    *observed = -((int)code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_observe_req2(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_REQ code,
 | 
			
		||||
    GBinderLocalRequest* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    int* observed = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("low prio observed req %d", code);
 | 
			
		||||
    g_assert_cmpint(*observed, == ,-((int)code));
 | 
			
		||||
    *observed = code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_observe_resp1(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_RESP code,
 | 
			
		||||
    const RadioResponseInfo* info,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    int* observed = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("high prio observed resp %d", code);
 | 
			
		||||
    g_assert(!*observed);
 | 
			
		||||
    *observed = -((int)code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_observe_resp2(
 | 
			
		||||
    RadioConfig* config,
 | 
			
		||||
    RADIO_CONFIG_RESP code,
 | 
			
		||||
    const RadioResponseInfo* info,
 | 
			
		||||
    const GBinderReader* args,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    int* observed = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("low prio observed resp %d", code);
 | 
			
		||||
    g_assert_cmpint(*observed, == ,-((int)code));
 | 
			
		||||
    *observed = code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_complete_cb(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_CONFIG_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple* test = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("resp %d", resp);
 | 
			
		||||
    g_assert_cmpint(status, == ,RADIO_TX_STATUS_OK);
 | 
			
		||||
    g_assert_cmpint(resp, == ,RADIO_CONFIG_RESP_SET_PREFERRED_DATA_MODEM);
 | 
			
		||||
    g_assert_cmpint(error, == ,RADIO_ERROR_NONE);
 | 
			
		||||
    g_assert(!test->completed);
 | 
			
		||||
    g_assert(!test->destroyed);
 | 
			
		||||
    test->completed = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple test;
 | 
			
		||||
    RadioConfig* client = test_simple_init(&test);
 | 
			
		||||
    RadioRequest* req = radio_config_request_new(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_SET_PREFERRED_DATA_MODEM, NULL,
 | 
			
		||||
        test_resp_complete_cb, test_simple_destroy_cb, &test);
 | 
			
		||||
    int observed_req = 0, observed_resp = 0;
 | 
			
		||||
    gulong id[4];
 | 
			
		||||
 | 
			
		||||
    id[0] = radio_config_add_request_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_HIGHEST, RADIO_CONFIG_REQ_ANY,
 | 
			
		||||
        test_resp_observe_req1, &observed_req);
 | 
			
		||||
    id[1] = radio_config_add_request_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_LOWEST, RADIO_CONFIG_REQ_ANY,
 | 
			
		||||
        test_resp_observe_req2, &observed_req);
 | 
			
		||||
    id[2] = radio_config_add_response_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_HIGHEST, RADIO_CONFIG_RESP_ANY,
 | 
			
		||||
        test_resp_observe_resp1, &observed_resp);
 | 
			
		||||
    id[3] = radio_config_add_response_observer_with_priority(client,
 | 
			
		||||
        RADIO_OBSERVER_PRIORITY_LOWEST, RADIO_CONFIG_RESP_ANY,
 | 
			
		||||
        test_resp_observe_resp2, &observed_resp);
 | 
			
		||||
 | 
			
		||||
    g_assert(radio_request_submit(req));
 | 
			
		||||
    radio_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    test_run(&test_opt, test.loop);
 | 
			
		||||
 | 
			
		||||
    g_assert(test.completed);
 | 
			
		||||
    g_assert(test.destroyed);
 | 
			
		||||
    g_assert_cmpint(observed_req,==,RADIO_CONFIG_REQ_SET_PREFERRED_DATA_MODEM);
 | 
			
		||||
    g_assert_cmpint(observed_resp,==,RADIO_CONFIG_RESP_SET_PREFERRED_DATA_MODEM);
 | 
			
		||||
 | 
			
		||||
    /* Cleanup */
 | 
			
		||||
    radio_config_remove_all_handlers(client, id);
 | 
			
		||||
    test_simple_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * cancel
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_cancel(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestCommon test;
 | 
			
		||||
    gboolean destroyed = FALSE;
 | 
			
		||||
    RadioConfig* client = test_common_init(&test, RADIO_CONFIG_INTERFACE_1_0);
 | 
			
		||||
    RadioRequest* req = radio_config_request_new(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_MODEMS_CONFIG, NULL,
 | 
			
		||||
        test_complete_not_reached, test_destroy_once, &destroyed);
 | 
			
		||||
 | 
			
		||||
    g_assert(radio_request_submit(req));
 | 
			
		||||
    radio_request_cancel(req);
 | 
			
		||||
    g_assert_cmpint(req->state, == ,RADIO_REQUEST_STATE_CANCELLED);
 | 
			
		||||
    radio_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    g_assert(destroyed);
 | 
			
		||||
    test_common_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * fail_tx
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_fail_tx(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestCommon test;
 | 
			
		||||
    gboolean destroyed = FALSE;
 | 
			
		||||
    RadioConfig* client = test_common_init(&test, RADIO_CONFIG_INTERFACE_1_0);
 | 
			
		||||
    RadioRequest* req = radio_config_request_new(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_MODEMS_CONFIG, NULL,
 | 
			
		||||
        test_complete_not_reached, test_destroy_once, &destroyed);
 | 
			
		||||
 | 
			
		||||
    g_assert(req);
 | 
			
		||||
    g_assert(req->serial);
 | 
			
		||||
 | 
			
		||||
    /* Fail one transaction */
 | 
			
		||||
    test_gbinder_client_tx_fail_count = 1;
 | 
			
		||||
 | 
			
		||||
    /* Request switches in the FAILED state */
 | 
			
		||||
    g_assert(req);
 | 
			
		||||
    g_assert(!radio_request_submit(req));
 | 
			
		||||
    g_assert_cmpint(req->state, == ,RADIO_REQUEST_STATE_FAILED);
 | 
			
		||||
 | 
			
		||||
    g_assert(!destroyed);
 | 
			
		||||
    radio_request_drop(req);
 | 
			
		||||
    g_assert(destroyed);
 | 
			
		||||
 | 
			
		||||
    test_common_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * death
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_death_complete_cb(
 | 
			
		||||
    RadioRequest* req,
 | 
			
		||||
    RADIO_TX_STATUS status,
 | 
			
		||||
    RADIO_CONFIG_RESP resp,
 | 
			
		||||
    RADIO_ERROR error,
 | 
			
		||||
    const GBinderReader* reader,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple* test = user_data;
 | 
			
		||||
 | 
			
		||||
    GDEBUG("status %u", status);
 | 
			
		||||
    g_assert_cmpint(status, == ,RADIO_TX_STATUS_FAILED);
 | 
			
		||||
    g_assert_cmpint(resp, == ,RADIO_CONFIG_RESP_NONE);
 | 
			
		||||
    g_assert_cmpint(error, == ,RADIO_ERROR_NONE);
 | 
			
		||||
    test->completed++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_death_destroy_cb(
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple* test = user_data;
 | 
			
		||||
 | 
			
		||||
    test->destroyed++;
 | 
			
		||||
    GDEBUG("done");
 | 
			
		||||
    g_assert_cmpint(test->completed, == ,test->destroyed);
 | 
			
		||||
    test_quit_later(test->loop);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_death(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    TestSimple test;
 | 
			
		||||
    RadioConfig* client = test_simple_init(&test);
 | 
			
		||||
    RadioRequest* req = radio_config_request_new(client,
 | 
			
		||||
        RADIO_CONFIG_REQ_GET_MODEMS_CONFIG, NULL,
 | 
			
		||||
        test_death_complete_cb, test_death_destroy_cb, &test);
 | 
			
		||||
    RADIO_CONFIG_INTERFACE v;
 | 
			
		||||
    int death_count = 0;
 | 
			
		||||
    gulong id = radio_config_add_death_handler(client, test_config_inc_cb,
 | 
			
		||||
        &death_count);
 | 
			
		||||
 | 
			
		||||
    g_assert(radio_request_submit(req));
 | 
			
		||||
    radio_request_unref(req);
 | 
			
		||||
 | 
			
		||||
    /* Kill the remote objects */
 | 
			
		||||
    g_assert(!radio_config_dead(client));
 | 
			
		||||
    for (v = RADIO_CONFIG_INTERFACE_1_0;
 | 
			
		||||
         v <= radio_config_interface(client); v++) {
 | 
			
		||||
        test_gbinder_remote_object_kill(test.common.remote[v]);
 | 
			
		||||
    }
 | 
			
		||||
    g_assert(radio_config_dead(client));
 | 
			
		||||
    g_assert_cmpint(death_count, == ,1);
 | 
			
		||||
 | 
			
		||||
    /* Now expect the request to fail */
 | 
			
		||||
    test_run(&test_opt, test.loop);
 | 
			
		||||
    g_assert(test.completed);
 | 
			
		||||
    g_assert(test.destroyed);
 | 
			
		||||
 | 
			
		||||
    /* Cleanup */
 | 
			
		||||
    radio_config_remove_handler(client, id);
 | 
			
		||||
    test_simple_cleanup(&test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_PREFIX "/config/"
 | 
			
		||||
#define TEST_(t) TEST_PREFIX t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("null"), test_null);
 | 
			
		||||
    g_test_add_func(TEST_("name"), test_name);
 | 
			
		||||
    g_test_add_func(TEST_("none"), test_none);
 | 
			
		||||
    g_test_add_func(TEST_("basic"), test_basic);
 | 
			
		||||
    g_test_add_func(TEST_("ind"), test_ind);
 | 
			
		||||
    g_test_add_func(TEST_("resp"), test_resp);
 | 
			
		||||
    g_test_add_func(TEST_("cancel"), test_cancel);
 | 
			
		||||
    g_test_add_func(TEST_("fail_tx"), test_fail_tx);
 | 
			
		||||
    g_test_add_func(TEST_("death"), test_death);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_instance/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_instance/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_instance
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										1207
									
								
								unit/unit_instance/unit_instance.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1207
									
								
								unit/unit_instance/unit_instance.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								unit/unit_registry/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_registry/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_registry
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										170
									
								
								unit/unit_registry/unit_registry.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								unit/unit_registry/unit_registry.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2021 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2021 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
 | 
			
		||||
#include "radio_instance.h"
 | 
			
		||||
#include "radio_registry_p.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * null
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_null(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    radio_registry_instance_added(NULL);
 | 
			
		||||
    radio_registry_instance_removed(NULL);
 | 
			
		||||
    radio_registry_remove_handler(NULL, 0);
 | 
			
		||||
    radio_registry_remove_handlers(NULL, NULL, 0);
 | 
			
		||||
    radio_registry_unref(NULL);
 | 
			
		||||
    g_assert(!radio_registry_ref(NULL));
 | 
			
		||||
    g_assert(!radio_registry_add_instance_added_handler(NULL,NULL,NULL,NULL));
 | 
			
		||||
    g_assert(!radio_registry_add_instance_removed_handler(NULL,NULL,NULL,NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * basic
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static const char* test_basic_key = "foo";
 | 
			
		||||
static const char* test_basic_bad_key = "bar";
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_basic_add_cb(
 | 
			
		||||
    RadioRegistry* registry,
 | 
			
		||||
    RadioInstance* radio,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    (*((int*)user_data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_basic_remove_cb(
 | 
			
		||||
    RadioRegistry* registry,
 | 
			
		||||
    const char* str,
 | 
			
		||||
    gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_assert_cmpstr(str, == ,test_basic_key);
 | 
			
		||||
    (*((int*)user_data))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_basic(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    RadioRegistry* reg = radio_registry_new();
 | 
			
		||||
    int add_count = 0, remove_count = 0;
 | 
			
		||||
    gulong id[6];
 | 
			
		||||
    GObject* instance;
 | 
			
		||||
 | 
			
		||||
    g_assert(reg);
 | 
			
		||||
    g_assert(reg == radio_registry_new()); /* New ref to the same instance */
 | 
			
		||||
    radio_registry_unref(reg);
 | 
			
		||||
 | 
			
		||||
    g_assert(!radio_registry_add_instance_added_handler(reg,NULL,NULL,NULL));
 | 
			
		||||
    g_assert(!radio_registry_add_instance_removed_handler(reg,NULL,NULL,NULL));
 | 
			
		||||
 | 
			
		||||
    /* Add/remove handlers */
 | 
			
		||||
    id[0] = radio_registry_add_instance_added_handler(reg, "",
 | 
			
		||||
        test_basic_add_cb, &add_count);
 | 
			
		||||
    radio_registry_remove_handler(reg, id[0]);
 | 
			
		||||
    id[0] = radio_registry_add_instance_added_handler(reg, NULL,
 | 
			
		||||
        test_basic_add_cb, &add_count);
 | 
			
		||||
    id[1] = radio_registry_add_instance_added_handler(reg, test_basic_bad_key,
 | 
			
		||||
        test_basic_add_cb, &add_count);  /* won't get called */
 | 
			
		||||
 | 
			
		||||
    id[2] = radio_registry_add_instance_removed_handler(reg, NULL,
 | 
			
		||||
        test_basic_remove_cb, &remove_count);
 | 
			
		||||
    id[3] = radio_registry_add_instance_removed_handler(reg, "",
 | 
			
		||||
        test_basic_remove_cb, &remove_count);
 | 
			
		||||
    id[4] = radio_registry_add_instance_removed_handler(reg, test_basic_key,
 | 
			
		||||
        test_basic_remove_cb, &remove_count);
 | 
			
		||||
    id[5] = radio_registry_add_instance_removed_handler(reg, test_basic_bad_key,
 | 
			
		||||
        test_basic_remove_cb, &remove_count); /* won't get called */
 | 
			
		||||
 | 
			
		||||
    /* Well, this wouldn't be a real functional instance but we don't care */
 | 
			
		||||
    instance = g_object_new(RADIO_TYPE_INSTANCE, NULL);
 | 
			
		||||
    radio_registry_instance_added(RADIO_INSTANCE(instance));
 | 
			
		||||
    g_assert_cmpint(add_count, == ,1); /* 1 out of 2 is called */
 | 
			
		||||
    g_assert_cmpint(remove_count, == ,0);
 | 
			
		||||
 | 
			
		||||
    radio_registry_instance_removed(test_basic_key);
 | 
			
		||||
    g_assert_cmpint(add_count, == ,1);
 | 
			
		||||
    g_assert_cmpint(remove_count, == ,3); /* 3 our of 4 are called */
 | 
			
		||||
    g_object_unref(instance);
 | 
			
		||||
 | 
			
		||||
    /* remove_all zeros the ids */
 | 
			
		||||
    radio_registry_remove_all_handlers(reg, id);
 | 
			
		||||
    g_assert(!id[0]);
 | 
			
		||||
    g_assert(!id[4]);
 | 
			
		||||
 | 
			
		||||
    radio_registry_remove_handler(reg, 0); /* No effect */
 | 
			
		||||
    radio_registry_unref(reg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_PREFIX "/registry/"
 | 
			
		||||
#define TEST_(t) TEST_PREFIX t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("null"), test_null);
 | 
			
		||||
    g_test_add_func(TEST_("basic"), test_basic);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
							
								
								
									
										5
									
								
								unit/unit_util/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								unit/unit_util/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
# -*- Mode: makefile-gmake -*-
 | 
			
		||||
 | 
			
		||||
EXE = unit_util
 | 
			
		||||
 | 
			
		||||
include ../common/Makefile
 | 
			
		||||
							
								
								
									
										370
									
								
								unit/unit_util/unit_util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										370
									
								
								unit/unit_util/unit_util.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,370 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2022 Jolla Ltd.
 | 
			
		||||
 * Copyright (C) 2022 Slava Monich <slava.monich@jolla.com>
 | 
			
		||||
 *
 | 
			
		||||
 * You may use this file under the terms of the BSD license as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 *   1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *      documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *   3. Neither the names of the copyright holders nor the names of its
 | 
			
		||||
 *      contributors may be used to endorse or promote products derived
 | 
			
		||||
 *      from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
			
		||||
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
 | 
			
		||||
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
			
		||||
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 | 
			
		||||
 * THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 *
 | 
			
		||||
 * The views and conclusions contained in the software and documentation
 | 
			
		||||
 * are those of the authors and should not be interpreted as representing
 | 
			
		||||
 * any official policies, either expressed or implied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
 | 
			
		||||
#include "radio_util.h"
 | 
			
		||||
 | 
			
		||||
#define UNKNOWN_VALUE (0x7fffffff)
 | 
			
		||||
#define UNKNOWN_REQ ((RADIO_REQ)UNKNOWN_VALUE)
 | 
			
		||||
#define UNKNOWN_IND ((RADIO_REQ)UNKNOWN_VALUE)
 | 
			
		||||
#define UNKNOWN_RESP ((RADIO_RESP)UNKNOWN_VALUE)
 | 
			
		||||
 | 
			
		||||
static TestOpt test_opt;
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * req_name
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_req_name(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!radio_req_name(UNKNOWN_REQ));
 | 
			
		||||
    g_assert(!radio_req_name(RADIO_REQ_ANY));
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_GET_ICC_CARD_STATUS),==,
 | 
			
		||||
        "getIccCardStatus");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_START_NETWORK_SCAN),==,
 | 
			
		||||
        "startNetworkScan");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA),==,
 | 
			
		||||
        "setSignalStrengthReportingCriteria");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_SET_SYSTEM_SELECTION_CHANNELS),==,
 | 
			
		||||
        "setSystemSelectionChannels");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_EMERGENCY_DIAL),==,
 | 
			
		||||
        "emergencyDial");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_ENABLE_UICC_APPLICATIONS),==,
 | 
			
		||||
        "enableUiccApplications");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_START_NETWORK_SCAN_1_4),==,
 | 
			
		||||
        "startNetworkScan_1_4");
 | 
			
		||||
    g_assert_cmpstr(radio_req_name(RADIO_REQ_START_NETWORK_SCAN_1_5),==,
 | 
			
		||||
        "startNetworkScan_1_5");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * resp_name
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_resp_name(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!radio_resp_name(UNKNOWN_RESP));
 | 
			
		||||
    g_assert(!radio_resp_name(RADIO_RESP_ANY));
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_GET_ICC_CARD_STATUS),==,
 | 
			
		||||
        "getIccCardStatusResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_START_NETWORK_SCAN),==,
 | 
			
		||||
        "startNetworkScanResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA),==,
 | 
			
		||||
        "setSignalStrengthReportingCriteriaResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_SET_SYSTEM_SELECTION_CHANNELS),==,
 | 
			
		||||
        "setSystemSelectionChannelsResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_EMERGENCY_DIAL),==,
 | 
			
		||||
        "emergencyDialResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_ENABLE_UICC_APPLICATIONS),==,
 | 
			
		||||
        "enableUiccApplicationsResponse");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_START_NETWORK_SCAN_1_4),==,
 | 
			
		||||
        "startNetworkScanResponse_1_4");
 | 
			
		||||
    g_assert_cmpstr(radio_resp_name(RADIO_RESP_START_NETWORK_SCAN_1_5),==,
 | 
			
		||||
        "startNetworkScanResponse_1_5");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * ind_name
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_ind_name(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    g_assert(!radio_ind_name(UNKNOWN_IND));
 | 
			
		||||
    g_assert(!radio_ind_name(RADIO_IND_ANY));
 | 
			
		||||
    g_assert_cmpstr(radio_ind_name(RADIO_IND_RADIO_STATE_CHANGED),==,
 | 
			
		||||
        "radioStateChanged");
 | 
			
		||||
    g_assert_cmpstr(radio_ind_name(RADIO_IND_NETWORK_SCAN_RESULT),==,
 | 
			
		||||
        "networkScanResult");
 | 
			
		||||
    g_assert_cmpstr(radio_ind_name(RADIO_IND_CURRENT_LINK_CAPACITY_ESTIMATE),==,
 | 
			
		||||
        "currentLinkCapacityEstimate");
 | 
			
		||||
    g_assert_cmpstr(radio_ind_name(RADIO_IND_CURRENT_EMERGENCY_NUMBER_LIST),==,
 | 
			
		||||
        "currentEmergencyNumberList");
 | 
			
		||||
    g_assert_cmpstr(radio_ind_name(RADIO_IND_REGISTRATION_FAILED),==,
 | 
			
		||||
        "registrationFailed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * req_resp
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_req_resp(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const struct radio_req_resp_data {
 | 
			
		||||
        RADIO_REQ req;
 | 
			
		||||
        RADIO_RESP resp;
 | 
			
		||||
    } tests[] = {
 | 
			
		||||
        { UNKNOWN_REQ, RADIO_RESP_NONE },
 | 
			
		||||
        { RADIO_REQ_ANY, RADIO_RESP_NONE },
 | 
			
		||||
        { RADIO_REQ_SETUP_DATA_CALL_1_2, RADIO_RESP_SETUP_DATA_CALL },
 | 
			
		||||
        { RADIO_REQ_DEACTIVATE_DATA_CALL_1_2, RADIO_RESP_DEACTIVATE_DATA_CALL },
 | 
			
		||||
        { RADIO_REQ_START_NETWORK_SCAN_1_2, RADIO_RESP_START_NETWORK_SCAN },
 | 
			
		||||
        { RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4,
 | 
			
		||||
          RADIO_RESP_SET_INITIAL_ATTACH_APN },
 | 
			
		||||
        { RADIO_REQ_SET_DATA_PROFILE_1_4, RADIO_RESP_SET_DATA_PROFILE },
 | 
			
		||||
        { RADIO_REQ_SET_INDICATION_FILTER_1_2,
 | 
			
		||||
          RADIO_RESP_SET_INDICATION_FILTER },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_RESP_GET_ICC_CARD_STATUS },
 | 
			
		||||
        { RADIO_REQ_START_NETWORK_SCAN, RADIO_RESP_START_NETWORK_SCAN },
 | 
			
		||||
        { RADIO_REQ_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA,
 | 
			
		||||
          RADIO_RESP_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA },
 | 
			
		||||
        { RADIO_REQ_SET_SYSTEM_SELECTION_CHANNELS,
 | 
			
		||||
          RADIO_RESP_SET_SYSTEM_SELECTION_CHANNELS },
 | 
			
		||||
        { RADIO_REQ_EMERGENCY_DIAL, RADIO_RESP_EMERGENCY_DIAL }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(tests); i++) {
 | 
			
		||||
        g_assert_cmpint(radio_req_resp(tests[i].req), ==, tests[i].resp);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * req_resp2
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
static
 | 
			
		||||
void
 | 
			
		||||
test_req_resp2(
 | 
			
		||||
    void)
 | 
			
		||||
{
 | 
			
		||||
    static const struct radio_req_resp2_data {
 | 
			
		||||
        RADIO_REQ req;
 | 
			
		||||
        RADIO_INTERFACE iface;
 | 
			
		||||
        RADIO_RESP resp;
 | 
			
		||||
    } tests[] = {
 | 
			
		||||
        { UNKNOWN_REQ, RADIO_INTERFACE_NONE, RADIO_RESP_NONE },
 | 
			
		||||
        { RADIO_REQ_SUPPLY_ICC_PIN_FOR_APP, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_SUPPLY_ICC_PIN_FOR_APP },
 | 
			
		||||
        { RADIO_REQ_SUPPLY_ICC_PUK_FOR_APP, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_SUPPLY_ICC_PUK_FOR_APP },
 | 
			
		||||
        { RADIO_REQ_SUPPLY_ICC_PIN2_FOR_APP, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_SUPPLY_ICC_PIN2_FOR_APP },
 | 
			
		||||
        { RADIO_REQ_SUPPLY_ICC_PUK2_FOR_APP, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_SUPPLY_ICC_PUK2_FOR_APP },
 | 
			
		||||
        { RADIO_REQ_CHANGE_ICC_PIN_FOR_APP, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_CHANGE_ICC_PIN_FOR_APP },
 | 
			
		||||
        { RADIO_REQ_CHANGE_ICC_PIN2_FOR_APP, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_CHANGE_ICC_PIN2_FOR_APP },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_SETUP_DATA_CALL_1_2, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_SETUP_DATA_CALL },
 | 
			
		||||
        { RADIO_REQ_SETUP_DATA_CALL_1_2, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_SETUP_DATA_CALL },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_DEACTIVATE_DATA_CALL_1_2, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_DEACTIVATE_DATA_CALL },
 | 
			
		||||
        { RADIO_REQ_DEACTIVATE_DATA_CALL_1_2, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_DEACTIVATE_DATA_CALL },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_START_NETWORK_SCAN_1_2, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_START_NETWORK_SCAN },
 | 
			
		||||
        { RADIO_REQ_START_NETWORK_SCAN_1_2, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_START_NETWORK_SCAN },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_SET_INITIAL_ATTACH_APN_1_4, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_SET_INITIAL_ATTACH_APN },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_SET_DATA_PROFILE_1_4, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_SET_DATA_PROFILE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_SET_INDICATION_FILTER_1_2, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_SET_INDICATION_FILTER },
 | 
			
		||||
        { RADIO_REQ_SET_INDICATION_FILTER_1_2, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_SET_INDICATION_FILTER },
 | 
			
		||||
        { RADIO_REQ_SET_INDICATION_FILTER_1_5, RADIO_INTERFACE_1_5,
 | 
			
		||||
          RADIO_RESP_SET_INDICATION_FILTER_1_5 },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS_1_4 },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_1_5,
 | 
			
		||||
          RADIO_RESP_GET_ICC_CARD_STATUS_1_5 },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
        { RADIO_REQ_GET_ICC_CARD_STATUS, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST_1_4 },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_1_5,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST_1_5 },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_CELL_INFO_LIST_1_5 },
 | 
			
		||||
        { RADIO_REQ_GET_CELL_INFO_LIST, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_CURRENT_CALLS_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_CURRENT_CALLS, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_SIGNAL_STRENGTH_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_SIGNAL_STRENGTH, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_VOICE_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_VOICE_REGISTRATION_STATE, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_2 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_4 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_DATA_REGISTRATION_STATE_1_4 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_REGISTRATION_STATE, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE },
 | 
			
		||||
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_0,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_1,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_2,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_3,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_4,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST_1_4 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_1_5,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST_1_5 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_COUNT,
 | 
			
		||||
          RADIO_RESP_GET_DATA_CALL_LIST_1_5 },
 | 
			
		||||
        { RADIO_REQ_GET_DATA_CALL_LIST, RADIO_INTERFACE_NONE,
 | 
			
		||||
          RADIO_RESP_NONE }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(tests); i++) {
 | 
			
		||||
        g_assert_cmpint(radio_req_resp2(tests[i].req, tests[i].iface), ==,
 | 
			
		||||
            tests[i].resp);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
 * Common
 | 
			
		||||
 *==========================================================================*/
 | 
			
		||||
 | 
			
		||||
#define TEST_PREFIX "/util/"
 | 
			
		||||
#define TEST_(t) TEST_PREFIX t
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    g_test_init(&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func(TEST_("req_name"), test_req_name);
 | 
			
		||||
    g_test_add_func(TEST_("resp_name"), test_resp_name);
 | 
			
		||||
    g_test_add_func(TEST_("ind_name"), test_ind_name);
 | 
			
		||||
    g_test_add_func(TEST_("req_resp"), test_req_resp);
 | 
			
		||||
    g_test_add_func(TEST_("req_resp2"), test_req_resp2);
 | 
			
		||||
    test_init(&test_opt, argc, argv);
 | 
			
		||||
    return g_test_run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Local Variables:
 | 
			
		||||
 * mode: C
 | 
			
		||||
 * c-basic-offset: 4
 | 
			
		||||
 * indent-tabs-mode: nil
 | 
			
		||||
 * End:
 | 
			
		||||
 */
 | 
			
		||||
		Reference in New Issue
	
	Block a user