Compare commits
	
		
			1330 Commits
		
	
	
		
			libsigrok-
			...
			hw/sq50
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
									
								
								 | 
						b244ed5246 | |
| 
							
							
								
									
								
								 | 
						19a7aa375a | |
| 
							
							
								
									
								
								 | 
						243b525727 | |
| 
							
							
								
									
								
								 | 
						192cb0d897 | |
| 
							
							
								
									
								
								 | 
						2a815b8a5f | |
| 
							
							
								
									
								
								 | 
						acad3c2123 | |
| 
							
							
								
									
								
								 | 
						78cf266f90 | |
| 
							
							
								
									
								
								 | 
						32817ebeaa | |
| 
							
							
								
									
								
								 | 
						33758a51e7 | |
| 
							
							
								
									
								
								 | 
						d70c0bc625 | |
| 
							
							
								
									
								
								 | 
						638bdaec16 | |
| 
							
							
								
									
								
								 | 
						d1074befa3 | |
| 
							
							
								
									
								
								 | 
						d8f08acdc3 | |
| 
							
							
								
									
								
								 | 
						012becda49 | |
| 
							
							
								 | 
						b96051a507 | |
| 
							
							
								 | 
						8e5dbaf6e9 | |
| 
							
							
								 | 
						0498ef4e42 | |
| 
							
							
								 | 
						996331ce9b | |
| 
							
							
								 | 
						e333a40c1c | |
| 
							
							
								 | 
						59f6765508 | |
| 
							
							
								 | 
						321f85fb07 | |
| 
							
							
								 | 
						64d54a719a | |
| 
							
							
								 | 
						569165c0e4 | |
| 
							
							
								 | 
						8ef4fb3347 | |
| 
							
							
								 | 
						0e3c3c80b8 | |
| 
							
							
								 | 
						020df861e0 | |
| 
							
							
								 | 
						1e91a90f2a | |
| 
							
							
								 | 
						73c575cf9e | |
| 
							
							
								 | 
						ed78768225 | |
| 
							
							
								 | 
						7414fb55cb | |
| 
							
							
								 | 
						1b7d49db64 | |
| 
							
							
								 | 
						d8064712ce | |
| 
							
							
								 | 
						18426d1c0e | |
| 
							
							
								 | 
						e90551c3f8 | |
| 
							
							
								 | 
						08f023fe97 | |
| 
							
							
								 | 
						b74cc88d32 | |
| 
							
							
								 | 
						bf03e06d57 | |
| 
							
							
								 | 
						a36b21fb89 | |
| 
							
							
								 | 
						69498046f6 | |
| 
							
							
								 | 
						7f0463840a | |
| 
							
							
								 | 
						d822f54d52 | |
| 
							
							
								 | 
						2f464b6c85 | |
| 
							
							
								 | 
						d008c0273f | |
| 
							
							
								 | 
						6b4bdfbde8 | |
| 
							
							
								 | 
						9d6a896014 | |
| 
							
							
								 | 
						5bf642dbf8 | |
| 
							
							
								 | 
						ce96b696b5 | |
| 
							
							
								 | 
						1de14d67f1 | |
| 
							
							
								 | 
						a0418c20d8 | |
| 
							
							
								 | 
						7fcdc35e17 | |
| 
							
							
								 | 
						e3c852854f | |
| 
							
							
								 | 
						cae328b54c | |
| 
							
							
								 | 
						73816a8d8c | |
| 
							
							
								 | 
						84073e32ef | |
| 
							
							
								 | 
						191af3d9ca | |
| 
							
							
								 | 
						70158398f3 | |
| 
							
							
								 | 
						4da62209dd | |
| 
							
							
								 | 
						4fad41a8a4 | |
| 
							
							
								 | 
						83d38ed90a | |
| 
							
							
								 | 
						ff85a7f0ab | |
| 
							
							
								 | 
						36165cf0f7 | |
| 
							
							
								 | 
						9417f26fd4 | |
| 
							
							
								 | 
						1c50255506 | |
| 
							
							
								 | 
						c9cfcd2591 | |
| 
							
							
								 | 
						9b915e3a41 | |
| 
							
							
								 | 
						4c72966444 | |
| 
							
							
								 | 
						ac1866b923 | |
| 
							
							
								 | 
						f5c697bfe6 | |
| 
							
							
								 | 
						4efd5462c7 | |
| 
							
							
								 | 
						c899e691f3 | |
| 
							
							
								 | 
						4b8348941d | |
| 
							
							
								 | 
						7a78fd56f7 | |
| 
							
							
								 | 
						884ae8c021 | |
| 
							
							
								 | 
						d7a4dad881 | |
| 
							
							
								 | 
						584269fd2f | |
| 
							
							
								 | 
						12e7abe219 | |
| 
							
							
								 | 
						522381a343 | |
| 
							
							
								 | 
						004fd9ffd3 | |
| 
							
							
								 | 
						955ab60455 | |
| 
							
							
								 | 
						c3d4003710 | |
| 
							
							
								 | 
						d9a74e97f4 | |
| 
							
							
								 | 
						8f87c5284b | |
| 
							
							
								 | 
						797c8d9034 | |
| 
							
							
								 | 
						40a0b2f466 | |
| 
							
							
								 | 
						051d85f28d | |
| 
							
							
								 | 
						2111d1574b | |
| 
							
							
								 | 
						ddeaa49d43 | |
| 
							
							
								 | 
						33306b13ac | |
| 
							
							
								 | 
						5433907ed9 | |
| 
							
							
								 | 
						389acdd991 | |
| 
							
							
								 | 
						f5c618e55f | |
| 
							
							
								 | 
						b41562f6ce | |
| 
							
							
								 | 
						a99ff45359 | |
| 
							
							
								 | 
						fe185e4990 | |
| 
							
							
								 | 
						0f5dcee6ce | |
| 
							
							
								 | 
						a2916ad017 | |
| 
							
							
								 | 
						1145ceaa78 | |
| 
							
							
								 | 
						c93c014f47 | |
| 
							
							
								 | 
						c329b788d2 | |
| 
							
							
								 | 
						10fd326dea | |
| 
							
							
								 | 
						1c5d5905a4 | |
| 
							
							
								 | 
						7320ce5ecc | |
| 
							
							
								 | 
						3cc9e21573 | |
| 
							
							
								 | 
						f8fd84208d | |
| 
							
							
								 | 
						50b15953fe | |
| 
							
							
								 | 
						f20c39d933 | |
| 
							
							
								 | 
						c36a7d84ca | |
| 
							
							
								 | 
						29f15d52cb | |
| 
							
							
								 | 
						aad6b9de5f | |
| 
							
							
								 | 
						ba1fb5e926 | |
| 
							
							
								 | 
						4c29bba1f0 | |
| 
							
							
								 | 
						3fa436bb48 | |
| 
							
							
								 | 
						8fb9afcacd | |
| 
							
							
								 | 
						f93bf8ba02 | |
| 
							
							
								 | 
						6065d660e0 | |
| 
							
							
								 | 
						aa8e4959e2 | |
| 
							
							
								 | 
						d7ce5452ac | |
| 
							
							
								 | 
						30903c4043 | |
| 
							
							
								 | 
						3decd3b1f0 | |
| 
							
							
								 | 
						efce57da32 | |
| 
							
							
								 | 
						6bee394dee | |
| 
							
							
								 | 
						0931639a12 | |
| 
							
							
								 | 
						9a1a7dc283 | |
| 
							
							
								 | 
						27186edacf | |
| 
							
							
								 | 
						91ab2f6475 | |
| 
							
							
								 | 
						070668a0fd | |
| 
							
							
								 | 
						1a7adeac29 | |
| 
							
							
								 | 
						2cb4204c6f | |
| 
							
							
								 | 
						ec30291701 | |
| 
							
							
								 | 
						358105152a | |
| 
							
							
								 | 
						a3fe36d01e | |
| 
							
							
								 | 
						b1eb94bbef | |
| 
							
							
								 | 
						92cd85149a | |
| 
							
							
								 | 
						8c8fff4773 | |
| 
							
							
								 | 
						78b07caf11 | |
| 
							
							
								 | 
						f21b6983e8 | |
| 
							
							
								 | 
						c16effaedc | |
| 
							
							
								 | 
						34ce5b0439 | |
| 
							
							
								 | 
						d7838e4804 | |
| 
							
							
								 | 
						1f8ef363cb | |
| 
							
							
								 | 
						cd11e33c5d | |
| 
							
							
								 | 
						d999f2b61e | |
| 
							
							
								 | 
						9ce14905cb | |
| 
							
							
								 | 
						feeafbc003 | |
| 
							
							
								 | 
						a4be2b327b | |
| 
							
							
								 | 
						5a0303474c | |
| 
							
							
								 | 
						4c98253dba | |
| 
							
							
								 | 
						02feeb30b9 | |
| 
							
							
								 | 
						068db0fbe6 | |
| 
							
							
								 | 
						63eec38073 | |
| 
							
							
								 | 
						2dddd5bd5e | |
| 
							
							
								 | 
						0c52026459 | |
| 
							
							
								 | 
						7dd1dd9f7d | |
| 
							
							
								 | 
						6d8182b643 | |
| 
							
							
								 | 
						8e79890770 | |
| 
							
							
								 | 
						3f8453b274 | |
| 
							
							
								 | 
						66b349841a | |
| 
							
							
								 | 
						56213aa027 | |
| 
							
							
								 | 
						11addc897a | |
| 
							
							
								 | 
						648f32d119 | |
| 
							
							
								 | 
						3ad30b4e19 | |
| 
							
							
								 | 
						b1184024fe | |
| 
							
							
								 | 
						400bc4ffab | |
| 
							
							
								 | 
						abcb13855f | |
| 
							
							
								 | 
						ce3fe37969 | |
| 
							
							
								 | 
						e62b284c1c | |
| 
							
							
								 | 
						e4bcc63de6 | |
| 
							
							
								 | 
						6205515cc8 | |
| 
							
							
								 | 
						f37f11ec6b | |
| 
							
							
								 | 
						505a55f789 | |
| 
							
							
								 | 
						5208214739 | |
| 
							
							
								 | 
						565c8c3545 | |
| 
							
							
								 | 
						d2cc60bd45 | |
| 
							
							
								 | 
						fcacf532f5 | |
| 
							
							
								 | 
						003ad0ab8c | |
| 
							
							
								 | 
						f403cb9de9 | |
| 
							
							
								 | 
						22f76e188b | |
| 
							
							
								 | 
						bd5f0a143e | |
| 
							
							
								 | 
						24a953382c | |
| 
							
							
								 | 
						f91c6940ab | |
| 
							
							
								 | 
						395c1850b7 | |
| 
							
							
								 | 
						7d95afb9be | |
| 
							
							
								 | 
						6f9234e6f3 | |
| 
							
							
								 | 
						2755ab36f3 | |
| 
							
							
								 | 
						dcdc2848b7 | |
| 
							
							
								 | 
						58a75642e9 | |
| 
							
							
								 | 
						a80bed7656 | |
| 
							
							
								 | 
						a2b1a53bb4 | |
| 
							
							
								 | 
						f1a37f3924 | |
| 
							
							
								 | 
						0ccc6f7cdf | |
| 
							
							
								 | 
						b54d9b4974 | |
| 
							
							
								 | 
						fe8c5aef1f | |
| 
							
							
								 | 
						82ff704449 | |
| 
							
							
								 | 
						f5247d953f | |
| 
							
							
								 | 
						98b7b08956 | |
| 
							
							
								 | 
						ce384e074f | |
| 
							
							
								 | 
						66665b0932 | |
| 
							
							
								 | 
						a3ec8a9aa1 | |
| 
							
							
								 | 
						e37e301e26 | |
| 
							
							
								 | 
						d643e6bc39 | |
| 
							
							
								 | 
						048250d0e0 | |
| 
							
							
								 | 
						860ee00ab1 | |
| 
							
							
								 | 
						4c80a27284 | |
| 
							
							
								 | 
						25879a34e9 | |
| 
							
							
								 | 
						33aa8117e3 | |
| 
							
							
								 | 
						72cd558d4a | |
| 
							
							
								 | 
						6dc0007c71 | |
| 
							
							
								 | 
						4e5ff004d8 | |
| 
							
							
								 | 
						7eba792f0d | |
| 
							
							
								 | 
						868fc65ec3 | |
| 
							
							
								 | 
						d0b602f00f | |
| 
							
							
								 | 
						47e7a6395e | |
| 
							
							
								 | 
						a0ade2f933 | |
| 
							
							
								 | 
						d7df9dc738 | |
| 
							
							
								 | 
						4feb6ec9a2 | |
| 
							
							
								 | 
						01ac3eedfa | |
| 
							
							
								 | 
						b81cfbc349 | |
| 
							
							
								 | 
						d579755a66 | |
| 
							
							
								 | 
						0dc27cd1db | |
| 
							
							
								 | 
						13726d30b2 | |
| 
							
							
								 | 
						3b316fdca0 | |
| 
							
							
								 | 
						dc172c38d2 | |
| 
							
							
								 | 
						31907b76de | |
| 
							
							
								 | 
						cc835205cd | |
| 
							
							
								 | 
						3b93d3c24b | |
| 
							
							
								 | 
						f64f51b404 | |
| 
							
							
								 | 
						588295b8b9 | |
| 
							
							
								 | 
						9dde746023 | |
| 
							
							
								 | 
						85cff5cfba | |
| 
							
							
								 | 
						cb828f1b3e | |
| 
							
							
								 | 
						3b13990f7d | |
| 
							
							
								 | 
						f8a8d4bb70 | |
| 
							
							
								 | 
						9084c39608 | |
| 
							
							
								 | 
						d891892dc0 | |
| 
							
							
								 | 
						daa895cba3 | |
| 
							
							
								 | 
						dd8bec71c2 | |
| 
							
							
								 | 
						c03aaf342c | |
| 
							
							
								 | 
						8c5bd3d9c7 | |
| 
							
							
								 | 
						0ab36d2f54 | |
| 
							
							
								 | 
						47a102f9bb | |
| 
							
							
								 | 
						cb0fedd942 | |
| 
							
							
								 | 
						339d12df97 | |
| 
							
							
								 | 
						5f8cf332a6 | |
| 
							
							
								 | 
						bfc34b9ab0 | |
| 
							
							
								 | 
						f5083435cb | |
| 
							
							
								 | 
						34ce4d8258 | |
| 
							
							
								 | 
						e434f624ba | |
| 
							
							
								 | 
						1b8a37c688 | |
| 
							
							
								 | 
						50bc52f3a6 | |
| 
							
							
								 | 
						98c7ef378c | |
| 
							
							
								 | 
						7c48d434f0 | |
| 
							
							
								 | 
						025bd56f10 | |
| 
							
							
								 | 
						e2283318c1 | |
| 
							
							
								 | 
						6999029585 | |
| 
							
							
								 | 
						16e96ca3af | |
| 
							
							
								 | 
						06ed999aa4 | |
| 
							
							
								 | 
						19f31c8ace | |
| 
							
							
								 | 
						8cbe5339b1 | |
| 
							
							
								 | 
						704910e32c | |
| 
							
							
								 | 
						1cbb3b1cfb | |
| 
							
							
								 | 
						418c99248c | |
| 
							
							
								 | 
						9b09360654 | |
| 
							
							
								 | 
						8b58a519e4 | |
| 
							
							
								 | 
						856433b26e | |
| 
							
							
								 | 
						2e199405e5 | |
| 
							
							
								 | 
						35be304ba6 | |
| 
							
							
								 | 
						3f48ab0282 | |
| 
							
							
								 | 
						36962abf53 | |
| 
							
							
								 | 
						b2b6dd55ec | |
| 
							
							
								 | 
						f2cd2debf9 | |
| 
							
							
								 | 
						cae33a5874 | |
| 
							
							
								 | 
						219c63ea1b | |
| 
							
							
								 | 
						4ea012bdf5 | |
| 
							
							
								 | 
						8b607a24e7 | |
| 
							
							
								 | 
						ef2196712c | |
| 
							
							
								 | 
						18698b40d1 | |
| 
							
							
								 | 
						0cc3d090b7 | |
| 
							
							
								 | 
						cbfaf5e073 | |
| 
							
							
								 | 
						ebc5110989 | |
| 
							
							
								 | 
						3094e9d8ca | |
| 
							
							
								 | 
						5cc292b34a | |
| 
							
							
								 | 
						e092671365 | |
| 
							
							
								 | 
						f14e6f7e1a | |
| 
							
							
								 | 
						debe1ff66d | |
| 
							
							
								 | 
						914f8160e7 | |
| 
							
							
								 | 
						8a72362505 | |
| 
							
							
								 | 
						66d1790cc0 | |
| 
							
							
								 | 
						16a5d5ac7d | |
| 
							
							
								 | 
						1385f791b0 | |
| 
							
							
								 | 
						ee5cef7103 | |
| 
							
							
								 | 
						de4c29fa91 | |
| 
							
							
								 | 
						ea57157d0d | |
| 
							
							
								 | 
						3f5f548410 | |
| 
							
							
								 | 
						156b6879e9 | |
| 
							
							
								 | 
						fb65ca09b7 | |
| 
							
							
								 | 
						8a57728d0e | |
| 
							
							
								 | 
						3d9373af2e | |
| 
							
							
								 | 
						53c8a99c41 | |
| 
							
							
								 | 
						8bd4dc8799 | |
| 
							
							
								 | 
						17ed72cc44 | |
| 
							
							
								 | 
						dbb3e2ad3d | |
| 
							
							
								 | 
						7718f3ca8f | |
| 
							
							
								 | 
						2d8a508976 | |
| 
							
							
								 | 
						16791da9c9 | |
| 
							
							
								 | 
						7dd766e0aa | |
| 
							
							
								 | 
						72ea3b84bd | |
| 
							
							
								 | 
						0f017b7da9 | |
| 
							
							
								 | 
						419f109505 | |
| 
							
							
								 | 
						abcd477196 | |
| 
							
							
								 | 
						a426f74aca | |
| 
							
							
								 | 
						7fe1f91f75 | |
| 
							
							
								 | 
						88a5f9eabe | |
| 
							
							
								 | 
						5c231fc466 | |
| 
							
							
								 | 
						9334ed6ccd | |
| 
							
							
								 | 
						2a62a9c44e | |
| 
							
							
								 | 
						a53b8e4d74 | |
| 
							
							
								 | 
						9b4d261fab | |
| 
							
							
								 | 
						b65649f6b9 | |
| 
							
							
								 | 
						c749d1ca57 | |
| 
							
							
								 | 
						80e717b3cf | |
| 
							
							
								 | 
						1bb9dc8217 | |
| 
							
							
								 | 
						5e78a56481 | |
| 
							
							
								 | 
						98b43eb3cd | |
| 
							
							
								 | 
						2c33b09255 | |
| 
							
							
								 | 
						7c41c420aa | |
| 
							
							
								 | 
						07411a605e | |
| 
							
							
								 | 
						9fb4c6324d | |
| 
							
							
								 | 
						dc0906e21c | |
| 
							
							
								 | 
						53a939aba5 | |
| 
							
							
								 | 
						742368a2bc | |
| 
							
							
								 | 
						97aa41e9b5 | |
| 
							
							
								 | 
						d770bfbbbc | |
| 
							
							
								 | 
						080b6bcf09 | |
| 
							
							
								 | 
						f1833600a0 | |
| 
							
							
								 | 
						f2a9a7c2c8 | |
| 
							
							
								 | 
						883db4dad1 | |
| 
							
							
								 | 
						1c8110dbc7 | |
| 
							
							
								 | 
						6d2e307016 | |
| 
							
							
								 | 
						de4dc45eae | |
| 
							
							
								 | 
						9785891436 | |
| 
							
							
								 | 
						77f3c5e51f | |
| 
							
							
								 | 
						8c381a353c | |
| 
							
							
								 | 
						00f3c94386 | |
| 
							
							
								 | 
						ff5fb18526 | |
| 
							
							
								 | 
						6cfc6c5c7a | |
| 
							
							
								 | 
						4c5ac0cf5b | |
| 
							
							
								 | 
						4704f64551 | |
| 
							
							
								 | 
						1d657f47be | |
| 
							
							
								 | 
						8f3c77db26 | |
| 
							
							
								 | 
						f0aec55605 | |
| 
							
							
								 | 
						4c5f70063a | |
| 
							
							
								 | 
						7f7702b81b | |
| 
							
							
								 | 
						0fa71943e3 | |
| 
							
							
								 | 
						447c4216fc | |
| 
							
							
								 | 
						10cf811385 | |
| 
							
							
								 | 
						148cf8bea1 | |
| 
							
							
								 | 
						88daa0536c | |
| 
							
							
								 | 
						c8dcd3ab72 | |
| 
							
							
								 | 
						082ca8d8bc | |
| 
							
							
								 | 
						78d78afb57 | |
| 
							
							
								 | 
						3ff6cfeebe | |
| 
							
							
								 | 
						69c5d959e7 | |
| 
							
							
								 | 
						56a1bf7b4b | |
| 
							
							
								 | 
						ca7d442692 | |
| 
							
							
								 | 
						35037b1d8b | |
| 
							
							
								 | 
						5ff772410b | |
| 
							
							
								 | 
						5652085a4e | |
| 
							
							
								 | 
						49d130200d | |
| 
							
							
								 | 
						c9901879f6 | |
| 
							
							
								 | 
						e803574173 | |
| 
							
							
								 | 
						6762401d2b | |
| 
							
							
								 | 
						82b9f3d116 | |
| 
							
							
								 | 
						deaaebb28d | |
| 
							
							
								 | 
						b4066aa80e | |
| 
							
							
								 | 
						4e9e767be0 | |
| 
							
							
								 | 
						b07a07fec2 | |
| 
							
							
								 | 
						2faa1db033 | |
| 
							
							
								 | 
						e2bd01f4a7 | |
| 
							
							
								 | 
						d7357ebbb6 | |
| 
							
							
								 | 
						20680f58ff | |
| 
							
							
								 | 
						bfa79fbdb6 | |
| 
							
							
								 | 
						440810958c | |
| 
							
							
								 | 
						f73b00b647 | |
| 
							
							
								 | 
						f5c863e572 | |
| 
							
							
								 | 
						7415217ede | |
| 
							
							
								 | 
						c4a46475a6 | |
| 
							
							
								 | 
						781ae4484d | |
| 
							
							
								 | 
						8491cf7cad | |
| 
							
							
								 | 
						f0362f595a | |
| 
							
							
								 | 
						e47e23355f | |
| 
							
							
								 | 
						4c660b46c1 | |
| 
							
							
								 | 
						f0901a5050 | |
| 
							
							
								 | 
						31b4a9a236 | |
| 
							
							
								 | 
						5a27356705 | |
| 
							
							
								 | 
						d649ff2290 | |
| 
							
							
								 | 
						c810ad60b4 | |
| 
							
							
								 | 
						aca2b460cc | |
| 
							
							
								 | 
						9b1101d621 | |
| 
							
							
								 | 
						23669c3df3 | |
| 
							
							
								 | 
						212769c3b8 | |
| 
							
							
								 | 
						51e60cde09 | |
| 
							
							
								 | 
						811dcf7ea9 | |
| 
							
							
								 | 
						307b239390 | |
| 
							
							
								 | 
						fbefa03f58 | |
| 
							
							
								 | 
						cb3b80512e | |
| 
							
							
								 | 
						05719d75aa | |
| 
							
							
								 | 
						cd7c5f9655 | |
| 
							
							
								 | 
						43e1e23a11 | |
| 
							
							
								 | 
						7e4e65bf65 | |
| 
							
							
								 | 
						fc3b42e93a | |
| 
							
							
								 | 
						08eb955a69 | |
| 
							
							
								 | 
						3f1f63f007 | |
| 
							
							
								 | 
						a267bf450c | |
| 
							
							
								 | 
						43bdef2634 | |
| 
							
							
								 | 
						5ada72fc0a | |
| 
							
							
								 | 
						9e7af34eaf | |
| 
							
							
								 | 
						5a9711764d | |
| 
							
							
								 | 
						72903e9d55 | |
| 
							
							
								 | 
						1a920e33fe | |
| 
							
							
								 | 
						2142a79b53 | |
| 
							
							
								 | 
						ef0b9935cf | |
| 
							
							
								 | 
						836fac9cf6 | |
| 
							
							
								 | 
						f6dcb3200d | |
| 
							
							
								 | 
						e53f32d2b8 | |
| 
							
							
								 | 
						de8fe3b515 | |
| 
							
							
								 | 
						246aca5f54 | |
| 
							
							
								 | 
						626c388abf | |
| 
							
							
								 | 
						dbc38383b2 | |
| 
							
							
								 | 
						19267272d3 | |
| 
							
							
								 | 
						9eab4435f0 | |
| 
							
							
								 | 
						b2c4dde226 | |
| 
							
							
								 | 
						c6aa9870b4 | |
| 
							
							
								 | 
						ad6a2beec3 | |
| 
							
							
								 | 
						e05f18273d | |
| 
							
							
								 | 
						affaf54012 | |
| 
							
							
								 | 
						539188e524 | |
| 
							
							
								 | 
						17c30d0593 | |
| 
							
							
								 | 
						4ddea31451 | |
| 
							
							
								 | 
						3895064542 | |
| 
							
							
								 | 
						7a0d1bdc20 | |
| 
							
							
								 | 
						dd5735c998 | |
| 
							
							
								 | 
						40f812f5dc | |
| 
							
							
								 | 
						675cb86f15 | |
| 
							
							
								 | 
						7812a5c802 | |
| 
							
							
								 | 
						e5137b9343 | |
| 
							
							
								 | 
						ccf68765aa | |
| 
							
							
								 | 
						84b4f9a1ff | |
| 
							
							
								 | 
						e3f86ef5fc | |
| 
							
							
								 | 
						599f9e1deb | |
| 
							
							
								 | 
						349c5e5432 | |
| 
							
							
								 | 
						dc40081706 | |
| 
							
							
								 | 
						a16198316f | |
| 
							
							
								 | 
						cf6beeb20d | |
| 
							
							
								 | 
						24931412ee | |
| 
							
							
								 | 
						19ab8e363e | |
| 
							
							
								 | 
						253d653d4d | |
| 
							
							
								 | 
						2e129b8b25 | |
| 
							
							
								 | 
						8da30037cf | |
| 
							
							
								 | 
						dfdf4c83ff | |
| 
							
							
								 | 
						cce6a8a1b7 | |
| 
							
							
								 | 
						aff2094193 | |
| 
							
							
								 | 
						c9b187a607 | |
| 
							
							
								 | 
						7c0891b0b8 | |
| 
							
							
								 | 
						ef62ab6c73 | |
| 
							
							
								 | 
						ad4174c1d8 | |
| 
							
							
								 | 
						cfdc80151b | |
| 
							
							
								 | 
						f216309fd0 | |
| 
							
							
								 | 
						76dea519e4 | |
| 
							
							
								 | 
						113de3a572 | |
| 
							
							
								 | 
						0f92d5db03 | |
| 
							
							
								 | 
						f314d87111 | |
| 
							
							
								 | 
						2489de3a24 | |
| 
							
							
								 | 
						59d916fe67 | |
| 
							
							
								 | 
						ebcd1aba01 | |
| 
							
							
								 | 
						02a8c07d89 | |
| 
							
							
								 | 
						2da97803e6 | |
| 
							
							
								 | 
						1656cd4a4a | |
| 
							
							
								 | 
						6d8205ad9a | |
| 
							
							
								 | 
						f6129c8f0c | |
| 
							
							
								 | 
						4d8338bb96 | |
| 
							
							
								 | 
						b1b8a7d079 | |
| 
							
							
								 | 
						b50970a541 | |
| 
							
							
								 | 
						66c300c4a6 | |
| 
							
							
								 | 
						c4d2e6fa5e | |
| 
							
							
								 | 
						0fb4512125 | |
| 
							
							
								 | 
						60117e6e9a | |
| 
							
							
								 | 
						ea9e7a3e82 | |
| 
							
							
								 | 
						1838d9f13f | |
| 
							
							
								 | 
						c38d69adf4 | |
| 
							
							
								 | 
						97a000748a | |
| 
							
							
								 | 
						29a9b1a0bd | |
| 
							
							
								 | 
						a12456f1bb | |
| 
							
							
								 | 
						0c96de7223 | |
| 
							
							
								 | 
						66ddc22a1d | |
| 
							
							
								 | 
						396af5ad7d | |
| 
							
							
								 | 
						a058de0410 | |
| 
							
							
								 | 
						0184aca19d | |
| 
							
							
								 | 
						b720f16eb5 | |
| 
							
							
								 | 
						aac3063300 | |
| 
							
							
								 | 
						3a247d0359 | |
| 
							
							
								 | 
						4f3cb1eaf7 | |
| 
							
							
								 | 
						1203acc78f | |
| 
							
							
								 | 
						39e1972347 | |
| 
							
							
								 | 
						3883934404 | |
| 
							
							
								 | 
						262061ff3d | |
| 
							
							
								 | 
						830e24b68f | |
| 
							
							
								 | 
						673989692c | |
| 
							
							
								 | 
						4fa4db2c79 | |
| 
							
							
								 | 
						c8ecfa6ea4 | |
| 
							
							
								 | 
						a9f3fa0548 | |
| 
							
							
								 | 
						4cf90b8667 | |
| 
							
							
								 | 
						e35ebc6aa3 | |
| 
							
							
								 | 
						e131be0ac3 | |
| 
							
							
								 | 
						3308450089 | |
| 
							
							
								 | 
						232eb33c67 | |
| 
							
							
								 | 
						bb0665868e | |
| 
							
							
								 | 
						d779dcacb7 | |
| 
							
							
								 | 
						6d0f3508f7 | |
| 
							
							
								 | 
						91525636a6 | |
| 
							
							
								 | 
						14cb6aa40a | |
| 
							
							
								 | 
						4fff7b3c8a | |
| 
							
							
								 | 
						1bb348cdbf | |
| 
							
							
								 | 
						80d3497569 | |
| 
							
							
								 | 
						e6bb2984e9 | |
| 
							
							
								 | 
						744d683ca7 | |
| 
							
							
								 | 
						0b0f40d864 | |
| 
							
							
								 | 
						6c6dd7328a | |
| 
							
							
								 | 
						1ac6436468 | |
| 
							
							
								 | 
						be7c63dcf8 | |
| 
							
							
								 | 
						c0aa074eb2 | |
| 
							
							
								 | 
						e378e3a2d4 | |
| 
							
							
								 | 
						3775ef8c7a | |
| 
							
							
								 | 
						d4f5170c39 | |
| 
							
							
								 | 
						a1771c26ba | |
| 
							
							
								 | 
						87307940f1 | |
| 
							
							
								 | 
						cb5cd1538f | |
| 
							
							
								 | 
						3f5473dde2 | |
| 
							
							
								 | 
						238b874e44 | |
| 
							
							
								 | 
						8556703a6c | |
| 
							
							
								 | 
						08ecb98e84 | |
| 
							
							
								 | 
						bf6b9e7b16 | |
| 
							
							
								 | 
						c87e9d26f4 | |
| 
							
							
								 | 
						a90ffc3730 | |
| 
							
							
								 | 
						92499a9c78 | |
| 
							
							
								 | 
						aa29b255f8 | |
| 
							
							
								 | 
						9451e01e77 | |
| 
							
							
								 | 
						66e19f47f4 | |
| 
							
							
								 | 
						01ae826ba3 | |
| 
							
							
								 | 
						03f169b36b | |
| 
							
							
								 | 
						e45a8de41c | |
| 
							
							
								 | 
						0cdb72c8f2 | |
| 
							
							
								 | 
						a89884c16c | |
| 
							
							
								 | 
						97c8fa70da | |
| 
							
							
								 | 
						b800667daf | |
| 
							
							
								 | 
						0759e2f55b | |
| 
							
							
								 | 
						7c7a112046 | |
| 
							
							
								 | 
						a10284cd18 | |
| 
							
							
								 | 
						0527cc3ad7 | |
| 
							
							
								 | 
						09c650d5e9 | |
| 
							
							
								 | 
						db3aac1a29 | |
| 
							
							
								 | 
						684b26ef18 | |
| 
							
							
								 | 
						bf5c4d46f8 | |
| 
							
							
								 | 
						67785f2568 | |
| 
							
							
								 | 
						e86cc12b66 | |
| 
							
							
								 | 
						10cfb04826 | |
| 
							
							
								 | 
						685ed70998 | |
| 
							
							
								 | 
						d03815a066 | |
| 
							
							
								 | 
						d478724801 | |
| 
							
							
								 | 
						2fba14d05a | |
| 
							
							
								 | 
						4ae1ab4555 | |
| 
							
							
								 | 
						575663ab6a | |
| 
							
							
								 | 
						f9c3df65c1 | |
| 
							
							
								 | 
						e2a391aabc | |
| 
							
							
								 | 
						0ec42cbdb2 | |
| 
							
							
								 | 
						07e42cb2cb | |
| 
							
							
								 | 
						b79c342278 | |
| 
							
							
								 | 
						7c8ae47dcb | |
| 
							
							
								 | 
						f085705f48 | |
| 
							
							
								 | 
						f736691d13 | |
| 
							
							
								 | 
						6e407e9850 | |
| 
							
							
								 | 
						164c5ae537 | |
| 
							
							
								 | 
						616bc3a170 | |
| 
							
							
								 | 
						828eeea227 | |
| 
							
							
								 | 
						edec0436db | |
| 
							
							
								 | 
						4417074c68 | |
| 
							
							
								 | 
						ad5aa993ae | |
| 
							
							
								 | 
						48b7c34629 | |
| 
							
							
								 | 
						1ac8c2181b | |
| 
							
							
								 | 
						bb15350e59 | |
| 
							
							
								 | 
						1df81f4b06 | |
| 
							
							
								 | 
						a7b8692ed0 | |
| 
							
							
								 | 
						f992151332 | |
| 
							
							
								 | 
						8c3df6e5cd | |
| 
							
							
								 | 
						ae4c1fb637 | |
| 
							
							
								 | 
						639c6f61c3 | |
| 
							
							
								 | 
						dca683ef99 | |
| 
							
							
								 | 
						e24e74ed84 | |
| 
							
							
								 | 
						18037e79f1 | |
| 
							
							
								 | 
						108d2ec2c2 | |
| 
							
							
								 | 
						ca9f8961e3 | |
| 
							
							
								 | 
						3535a6eeee | |
| 
							
							
								 | 
						dcd212f7a2 | |
| 
							
							
								 | 
						16a8e58068 | |
| 
							
							
								 | 
						878e0e9d21 | |
| 
							
							
								 | 
						271392d969 | |
| 
							
							
								 | 
						6213c38ef8 | |
| 
							
							
								 | 
						fcfa36fd6f | |
| 
							
							
								 | 
						fdcdfe53d8 | |
| 
							
							
								 | 
						e47a9562e9 | |
| 
							
							
								 | 
						7d0f52f7e5 | |
| 
							
							
								 | 
						4ddd34b107 | |
| 
							
							
								 | 
						f3178f123d | |
| 
							
							
								 | 
						98ed645e40 | |
| 
							
							
								 | 
						9e0693f92d | |
| 
							
							
								 | 
						052cc011bf | |
| 
							
							
								 | 
						d57a114347 | |
| 
							
							
								 | 
						262cb9968d | |
| 
							
							
								 | 
						8da8c8265f | |
| 
							
							
								 | 
						ddbe6880a0 | |
| 
							
							
								 | 
						b89e6db910 | |
| 
							
							
								 | 
						fd2433153a | |
| 
							
							
								 | 
						9652610080 | |
| 
							
							
								 | 
						26e96658ab | |
| 
							
							
								 | 
						5ce427c71b | |
| 
							
							
								 | 
						fdf0365257 | |
| 
							
							
								 | 
						f083ae63c7 | |
| 
							
							
								 | 
						0ad7074c9e | |
| 
							
							
								 | 
						dbc519f720 | |
| 
							
							
								 | 
						969671a542 | |
| 
							
							
								 | 
						3d1aa50f38 | |
| 
							
							
								 | 
						f2bbcc330a | |
| 
							
							
								 | 
						fe4bb77492 | |
| 
							
							
								 | 
						6188675b72 | |
| 
							
							
								 | 
						87aa1e63e3 | |
| 
							
							
								 | 
						7e66bf0586 | |
| 
							
							
								 | 
						8b5eadf427 | |
| 
							
							
								 | 
						43ff1110fb | |
| 
							
							
								 | 
						5e7377f4c7 | |
| 
							
							
								 | 
						7d1a4a5239 | |
| 
							
							
								 | 
						6449b2e035 | |
| 
							
							
								 | 
						1c0e1baaaa | |
| 
							
							
								 | 
						d1a3f3be45 | |
| 
							
							
								 | 
						8107a9a650 | |
| 
							
							
								 | 
						9618fde422 | |
| 
							
							
								 | 
						78ec6cf99d | |
| 
							
							
								 | 
						a6e5d2f676 | |
| 
							
							
								 | 
						94f364ec11 | |
| 
							
							
								 | 
						8430c9b62e | |
| 
							
							
								 | 
						a0bc8afd7d | |
| 
							
							
								 | 
						7ed4ae6307 | |
| 
							
							
								 | 
						628dc330bc | |
| 
							
							
								 | 
						d025fce937 | |
| 
							
							
								 | 
						27a9b6639e | |
| 
							
							
								 | 
						88e6a8da9c | |
| 
							
							
								 | 
						dfd1daf25f | |
| 
							
							
								 | 
						02d4db3562 | |
| 
							
							
								 | 
						1b6b9c01df | |
| 
							
							
								 | 
						8e249032d3 | |
| 
							
							
								 | 
						c54ca32340 | |
| 
							
							
								 | 
						f6ce25ec05 | |
| 
							
							
								 | 
						ec26d9e1df | |
| 
							
							
								 | 
						60143473c9 | |
| 
							
							
								 | 
						ae4e6999c5 | |
| 
							
							
								 | 
						a88114183a | |
| 
							
							
								 | 
						ea642977e5 | |
| 
							
							
								 | 
						4a34a74d73 | |
| 
							
							
								 | 
						aad0c77708 | |
| 
							
							
								 | 
						be15c51ed4 | |
| 
							
							
								 | 
						6e5a1a0178 | |
| 
							
							
								 | 
						6745488b1a | |
| 
							
							
								 | 
						082537602a | |
| 
							
							
								 | 
						f0e6b41f7a | |
| 
							
							
								 | 
						a0ba75bda2 | |
| 
							
							
								 | 
						4b3197828d | |
| 
							
							
								 | 
						2631d9320d | |
| 
							
							
								 | 
						9e11197246 | |
| 
							
							
								 | 
						bf700f679a | |
| 
							
							
								 | 
						de805ae50d | |
| 
							
							
								 | 
						ea7a83a437 | |
| 
							
							
								 | 
						47b821dc7d | |
| 
							
							
								 | 
						e150d55046 | |
| 
							
							
								 | 
						c3bfb95959 | |
| 
							
							
								 | 
						08e8c0e5bf | |
| 
							
							
								 | 
						0bad836f95 | |
| 
							
							
								 | 
						c7a51272a5 | |
| 
							
							
								 | 
						a9ed2eb069 | |
| 
							
							
								 | 
						62bd644f55 | |
| 
							
							
								 | 
						6f7e15090e | |
| 
							
							
								 | 
						fbbf21dcf5 | |
| 
							
							
								 | 
						f3549a1ccf | |
| 
							
							
								 | 
						942719b46c | |
| 
							
							
								 | 
						2868bca35b | |
| 
							
							
								 | 
						3f34a40268 | |
| 
							
							
								 | 
						3aadf5c479 | |
| 
							
							
								 | 
						e760f2cdaf | |
| 
							
							
								 | 
						bde6a99b33 | |
| 
							
							
								 | 
						a5c0259c4a | |
| 
							
							
								 | 
						d9a3c0b749 | |
| 
							
							
								 | 
						2887799404 | |
| 
							
							
								 | 
						08f3b427b6 | |
| 
							
							
								 | 
						64d03de1c2 | |
| 
							
							
								 | 
						1d2f9963ab | |
| 
							
							
								 | 
						31e65c62ec | |
| 
							
							
								 | 
						21bc4353f0 | |
| 
							
							
								 | 
						49b6732ec5 | |
| 
							
							
								 | 
						0617bb5a4e | |
| 
							
							
								 | 
						3e33089b72 | |
| 
							
							
								 | 
						4905215909 | |
| 
							
							
								 | 
						3cdad416e4 | |
| 
							
							
								 | 
						7a396ff5c5 | |
| 
							
							
								 | 
						a1ce15d4a1 | |
| 
							
							
								 | 
						a019bc48fd | |
| 
							
							
								 | 
						c10b0276da | |
| 
							
							
								 | 
						71db2d4d06 | |
| 
							
							
								 | 
						712f7d5e40 | |
| 
							
							
								 | 
						88c03eae85 | |
| 
							
							
								 | 
						3940abcb47 | |
| 
							
							
								 | 
						827139ef49 | |
| 
							
							
								 | 
						fa3d104f17 | |
| 
							
							
								 | 
						0be955d23d | |
| 
							
							
								 | 
						72b6f1c082 | |
| 
							
							
								 | 
						39ea7b7d39 | |
| 
							
							
								 | 
						59cae77e28 | |
| 
							
							
								 | 
						d10781808d | |
| 
							
							
								 | 
						6fc51fb1ee | |
| 
							
							
								 | 
						31f69b096f | |
| 
							
							
								 | 
						07182332f0 | |
| 
							
							
								 | 
						015df4ae8f | |
| 
							
							
								 | 
						1c3098aae0 | |
| 
							
							
								 | 
						388aa0fb6b | |
| 
							
							
								 | 
						023c6114c5 | |
| 
							
							
								 | 
						c90065a949 | |
| 
							
							
								 | 
						0540954d76 | |
| 
							
							
								 | 
						e5fa47c1c9 | |
| 
							
							
								 | 
						75aaf967e3 | |
| 
							
							
								 | 
						f1d0755b73 | |
| 
							
							
								 | 
						d8bc7ca3e6 | |
| 
							
							
								 | 
						08f8421a9e | |
| 
							
							
								 | 
						712f981dff | |
| 
							
							
								 | 
						fe71c7e42e | |
| 
							
							
								 | 
						4237ab9e5b | |
| 
							
							
								 | 
						76f712a73f | |
| 
							
							
								 | 
						11cf492183 | |
| 
							
							
								 | 
						2377246220 | |
| 
							
							
								 | 
						af930bcf7b | |
| 
							
							
								 | 
						7d40b5ee62 | |
| 
							
							
								 | 
						e91c9f6e25 | |
| 
							
							
								 | 
						48e2992f86 | |
| 
							
							
								 | 
						3ef305b079 | |
| 
							
							
								 | 
						bd10287e7c | |
| 
							
							
								 | 
						822a9c0eda | |
| 
							
							
								 | 
						56bcbbffd0 | |
| 
							
							
								 | 
						cd1e7fd20d | |
| 
							
							
								 | 
						5e5fde6e2c | |
| 
							
							
								 | 
						755793e991 | |
| 
							
							
								 | 
						3bae09ab9f | |
| 
							
							
								 | 
						3d11872282 | |
| 
							
							
								 | 
						88e4daa9ff | |
| 
							
							
								 | 
						49f7cb2425 | |
| 
							
							
								 | 
						cda70c2c19 | |
| 
							
							
								 | 
						04a0e0dc1c | |
| 
							
							
								 | 
						f696d27e05 | |
| 
							
							
								 | 
						ee1a7d2f9d | |
| 
							
							
								 | 
						653d087e15 | |
| 
							
							
								 | 
						0da8e0bd2b | |
| 
							
							
								 | 
						b736fa0c7d | |
| 
							
							
								 | 
						3ad0308c55 | |
| 
							
							
								 | 
						2efb3cd700 | |
| 
							
							
								 | 
						00f0016cc3 | |
| 
							
							
								 | 
						9be587a148 | |
| 
							
							
								 | 
						3bfdadf6df | |
| 
							
							
								 | 
						24fbd9f814 | |
| 
							
							
								 | 
						4be5746d1d | |
| 
							
							
								 | 
						1372bdcdb5 | |
| 
							
							
								 | 
						ee425a466a | |
| 
							
							
								 | 
						8bc8e9094c | |
| 
							
							
								 | 
						4d33f5e112 | |
| 
							
							
								 | 
						ac3625bef9 | |
| 
							
							
								 | 
						703fb45490 | |
| 
							
							
								 | 
						4465837b7d | |
| 
							
							
								 | 
						3831eaf9f4 | |
| 
							
							
								 | 
						4838c6ca5a | |
| 
							
							
								 | 
						fac36d0a77 | |
| 
							
							
								 | 
						13ac501acd | |
| 
							
							
								 | 
						77b6b98d1c | |
| 
							
							
								 | 
						1f9652a861 | |
| 
							
							
								 | 
						1f15efc1f7 | |
| 
							
							
								 | 
						932ef10f12 | |
| 
							
							
								 | 
						8a9788e2b7 | |
| 
							
							
								 | 
						ed18648423 | |
| 
							
							
								 | 
						8771222588 | |
| 
							
							
								 | 
						9d2e5483dc | |
| 
							
							
								 | 
						7f4c9a0444 | |
| 
							
							
								 | 
						38e7493dd1 | |
| 
							
							
								 | 
						b51288e3da | |
| 
							
							
								 | 
						b8fa29a175 | |
| 
							
							
								 | 
						a66099c6fa | |
| 
							
							
								 | 
						2f15f5bfec | |
| 
							
							
								 | 
						a54144c0bd | |
| 
							
							
								 | 
						8f6b0eb12a | |
| 
							
							
								 | 
						750303aab8 | |
| 
							
							
								 | 
						d37c6daa84 | |
| 
							
							
								 | 
						a4210e1890 | |
| 
							
							
								 | 
						17e0251d84 | |
| 
							
							
								 | 
						0875f11de4 | |
| 
							
							
								 | 
						19d816c54a | |
| 
							
							
								 | 
						0f5bba9622 | |
| 
							
							
								 | 
						081aaebfc7 | |
| 
							
							
								 | 
						74d915331a | |
| 
							
							
								 | 
						d875496366 | |
| 
							
							
								 | 
						7f5bfd6130 | |
| 
							
							
								 | 
						42408643f9 | |
| 
							
							
								 | 
						dd3202febf | |
| 
							
							
								 | 
						83a05ca9b3 | |
| 
							
							
								 | 
						ed367d6820 | |
| 
							
							
								 | 
						e6104296c2 | |
| 
							
							
								 | 
						9bf093011a | |
| 
							
							
								 | 
						51bf39a163 | |
| 
							
							
								 | 
						3387a5d8ee | |
| 
							
							
								 | 
						67b345b981 | |
| 
							
							
								 | 
						769561cbe9 | |
| 
							
							
								 | 
						0f523f2b45 | |
| 
							
							
								 | 
						9ad1d49c4c | |
| 
							
							
								 | 
						c26107b745 | |
| 
							
							
								 | 
						eb354840f0 | |
| 
							
							
								 | 
						55bece00aa | |
| 
							
							
								 | 
						e5b41b8d7e | |
| 
							
							
								 | 
						7e776c70b0 | |
| 
							
							
								 | 
						5e7ac9f9ec | |
| 
							
							
								 | 
						6b04525ba2 | |
| 
							
							
								 | 
						643c8824a5 | |
| 
							
							
								 | 
						6bcc81ac3a | |
| 
							
							
								 | 
						32054b0963 | |
| 
							
							
								 | 
						72cb20ed07 | |
| 
							
							
								 | 
						c5c6fa0f22 | |
| 
							
							
								 | 
						4a6751fd07 | |
| 
							
							
								 | 
						9456d63610 | |
| 
							
							
								 | 
						b8fcae5a12 | |
| 
							
							
								 | 
						10481ef05d | |
| 
							
							
								 | 
						ab2b21fb68 | |
| 
							
							
								 | 
						e756c595b6 | |
| 
							
							
								 | 
						f1e82915a8 | |
| 
							
							
								 | 
						380d3b2ae8 | |
| 
							
							
								 | 
						eaa8c6597b | |
| 
							
							
								 | 
						b872ab7d30 | |
| 
							
							
								 | 
						5eb39a91f3 | |
| 
							
							
								 | 
						bf2a6eeaa0 | |
| 
							
							
								 | 
						c7b5c3588e | |
| 
							
							
								 | 
						7b9387b8f0 | |
| 
							
							
								 | 
						264a4cb2b8 | |
| 
							
							
								 | 
						cbc656e45f | |
| 
							
							
								 | 
						583fc126d0 | |
| 
							
							
								 | 
						2dcd904c18 | |
| 
							
							
								 | 
						61803a29aa | |
| 
							
							
								 | 
						b8a954c586 | |
| 
							
							
								 | 
						f49065c668 | |
| 
							
							
								 | 
						bc294eaca8 | |
| 
							
							
								 | 
						2a80186103 | |
| 
							
							
								 | 
						caad0024fb | |
| 
							
							
								 | 
						3dc976fe9f | |
| 
							
							
								 | 
						4b75f84c01 | |
| 
							
							
								 | 
						2958315ded | |
| 
							
							
								 | 
						43d8603571 | |
| 
							
							
								 | 
						7a7afc0086 | |
| 
							
							
								 | 
						28f2d07fe5 | |
| 
							
							
								 | 
						9e850040db | |
| 
							
							
								 | 
						3c9117094c | |
| 
							
							
								 | 
						4c40d096d4 | |
| 
							
							
								 | 
						49d9a095e8 | |
| 
							
							
								 | 
						a38c2bfbbb | |
| 
							
							
								 | 
						1e99158c1b | |
| 
							
							
								 | 
						4299fcc0b8 | |
| 
							
							
								 | 
						d828b05e65 | |
| 
							
							
								 | 
						1c8901f744 | |
| 
							
							
								 | 
						7ca40d2d1c | |
| 
							
							
								 | 
						21ef355e50 | |
| 
							
							
								 | 
						49a468ed8b | |
| 
							
							
								 | 
						a61c8cce01 | |
| 
							
							
								 | 
						7e381bfc3c | |
| 
							
							
								 | 
						17a82e83ff | |
| 
							
							
								 | 
						fa2ce8c762 | |
| 
							
							
								 | 
						fd20e59caa | |
| 
							
							
								 | 
						1c5adc5ff7 | |
| 
							
							
								 | 
						0c8aedb543 | |
| 
							
							
								 | 
						0261956fab | |
| 
							
							
								 | 
						319fe9cea6 | |
| 
							
							
								 | 
						13ac09279a | |
| 
							
							
								 | 
						e8eb24222c | |
| 
							
							
								 | 
						20358f90b4 | |
| 
							
							
								 | 
						67765e465a | |
| 
							
							
								 | 
						090f1e1e54 | |
| 
							
							
								 | 
						b4580cb9d0 | |
| 
							
							
								 | 
						d5db6ea7e1 | |
| 
							
							
								 | 
						4fc4b8e7aa | |
| 
							
							
								 | 
						24801f4e80 | |
| 
							
							
								 | 
						092843eb42 | |
| 
							
							
								 | 
						c83bdde9da | |
| 
							
							
								 | 
						83df004be1 | |
| 
							
							
								 | 
						80430d4d20 | |
| 
							
							
								 | 
						8c4bff1d25 | |
| 
							
							
								 | 
						f54a55da2d | |
| 
							
							
								 | 
						0dabb880af | |
| 
							
							
								 | 
						54ee427df0 | |
| 
							
							
								 | 
						7102443a4a | |
| 
							
							
								 | 
						e1b115bd4d | |
| 
							
							
								 | 
						3601d50e26 | |
| 
							
							
								 | 
						0519db864b | |
| 
							
							
								 | 
						741bcf503d | |
| 
							
							
								 | 
						53ea24610e | |
| 
							
							
								 | 
						fb193945b6 | |
| 
							
							
								 | 
						0373343046 | |
| 
							
							
								 | 
						015f09702a | |
| 
							
							
								 | 
						817e759ddc | |
| 
							
							
								 | 
						cdb134eb19 | |
| 
							
							
								 | 
						55bcd7ad45 | |
| 
							
							
								 | 
						8a14fc0828 | |
| 
							
							
								 | 
						67070942cc | |
| 
							
							
								 | 
						2bd5d17c70 | |
| 
							
							
								 | 
						eca9772971 | |
| 
							
							
								 | 
						ce97fc3f6a | |
| 
							
							
								 | 
						350501d0c3 | |
| 
							
							
								 | 
						a5b9880eb2 | |
| 
							
							
								 | 
						74c4c1747f | |
| 
							
							
								 | 
						e80e1858ef | |
| 
							
							
								 | 
						972001561b | |
| 
							
							
								 | 
						2c267f6819 | |
| 
							
							
								 | 
						7c59d8f310 | |
| 
							
							
								 | 
						31c41782e4 | |
| 
							
							
								 | 
						d52107a159 | |
| 
							
							
								 | 
						567fe53822 | |
| 
							
							
								 | 
						2003be8cec | |
| 
							
							
								 | 
						1af7497d67 | |
| 
							
							
								 | 
						b20eb52055 | |
| 
							
							
								 | 
						9a4fd01af8 | |
| 
							
							
								 | 
						8bc2fa6d82 | |
| 
							
							
								 | 
						1fb31414f2 | |
| 
							
							
								 | 
						2cff7a2ba7 | |
| 
							
							
								 | 
						a33e4be826 | |
| 
							
							
								 | 
						408b6ab42b | |
| 
							
							
								 | 
						867293a101 | |
| 
							
							
								 | 
						d4b3f44fa7 | |
| 
							
							
								 | 
						b4bf6b3b4f | |
| 
							
							
								 | 
						330a32b240 | |
| 
							
							
								 | 
						cb8a0efc5c | |
| 
							
							
								 | 
						ec4806dcf5 | |
| 
							
							
								 | 
						9890fb1f08 | |
| 
							
							
								 | 
						c527132aec | |
| 
							
							
								 | 
						23d68466f8 | |
| 
							
							
								 | 
						66d2cc3a27 | |
| 
							
							
								 | 
						69b0558395 | |
| 
							
							
								 | 
						0549416e36 | |
| 
							
							
								 | 
						7b50a9b869 | |
| 
							
							
								 | 
						d4e0701771 | |
| 
							
							
								 | 
						366ccb8ab7 | |
| 
							
							
								 | 
						410883baf6 | |
| 
							
							
								 | 
						addb7340dd | |
| 
							
							
								 | 
						e843992dda | |
| 
							
							
								 | 
						823b0e29ae | |
| 
							
							
								 | 
						a551cb0927 | |
| 
							
							
								 | 
						b078dddb84 | |
| 
							
							
								 | 
						94cf02d0c2 | |
| 
							
							
								 | 
						a575c90e81 | |
| 
							
							
								 | 
						acc587ff24 | |
| 
							
							
								 | 
						c3f8e1abf0 | |
| 
							
							
								 | 
						cd97e39d89 | |
| 
							
							
								 | 
						fd8dc1db01 | |
| 
							
							
								 | 
						187c300b59 | |
| 
							
							
								 | 
						0aaaee2dd3 | |
| 
							
							
								 | 
						d7e348f481 | |
| 
							
							
								 | 
						2153093941 | |
| 
							
							
								 | 
						b3e715e528 | |
| 
							
							
								 | 
						706350360a | |
| 
							
							
								 | 
						3d70d77709 | |
| 
							
							
								 | 
						9edda1d25b | |
| 
							
							
								 | 
						a217289951 | |
| 
							
							
								 | 
						4389a54204 | |
| 
							
							
								 | 
						411b2f6822 | |
| 
							
							
								 | 
						f7711ed56c | |
| 
							
							
								 | 
						69229e5c15 | |
| 
							
							
								 | 
						093b8ff478 | |
| 
							
							
								 | 
						c372070333 | |
| 
							
							
								 | 
						7a65106e00 | |
| 
							
							
								 | 
						0f6ff97bf8 | |
| 
							
							
								 | 
						bdbb9151af | |
| 
							
							
								 | 
						fdf0744fa4 | |
| 
							
							
								 | 
						e8fd027120 | |
| 
							
							
								 | 
						fe06061d96 | |
| 
							
							
								 | 
						fe1aa53613 | |
| 
							
							
								 | 
						80eba3857a | |
| 
							
							
								 | 
						d8df3c2a01 | |
| 
							
							
								 | 
						93497d0016 | |
| 
							
							
								 | 
						6c1a76d126 | |
| 
							
							
								 | 
						7bbe5a2b6a | |
| 
							
							
								 | 
						90cc52260c | |
| 
							
							
								 | 
						21964348bc | |
| 
							
							
								 | 
						1e95832b3e | |
| 
							
							
								 | 
						dea7f6342a | |
| 
							
							
								 | 
						5a64d1d954 | |
| 
							
							
								 | 
						71e22ba88f | |
| 
							
							
								 | 
						3f4c1174b6 | |
| 
							
							
								 | 
						d9b716fc5f | |
| 
							
							
								 | 
						405b9c10eb | |
| 
							
							
								 | 
						1135f8d9c7 | |
| 
							
							
								 | 
						d6d87fa2a2 | |
| 
							
							
								 | 
						04c4a6776f | |
| 
							
							
								 | 
						6ddedf5bac | |
| 
							
							
								 | 
						d2c1730a28 | |
| 
							
							
								 | 
						1d9eebf4be | |
| 
							
							
								 | 
						374b0a94b2 | |
| 
							
							
								 | 
						65788048f0 | |
| 
							
							
								 | 
						e8e063738d | |
| 
							
							
								 | 
						567c6501d9 | |
| 
							
							
								 | 
						94b1d50642 | |
| 
							
							
								 | 
						7fb4ff0237 | |
| 
							
							
								 | 
						556a926d43 | |
| 
							
							
								 | 
						51e1f5661c | |
| 
							
							
								 | 
						e4fb1a821d | |
| 
							
							
								 | 
						8856f173df | |
| 
							
							
								 | 
						e5896840f6 | |
| 
							
							
								 | 
						641107aa6c | |
| 
							
							
								 | 
						2dedd64e11 | |
| 
							
							
								 | 
						a7f066bfca | |
| 
							
							
								 | 
						70cfec9a14 | |
| 
							
							
								 | 
						afcbb911f8 | |
| 
							
							
								 | 
						3e7fb88f21 | |
| 
							
							
								 | 
						4868f15a86 | |
| 
							
							
								 | 
						d18bf7bdfc | |
| 
							
							
								 | 
						a9a38e7511 | |
| 
							
							
								 | 
						04fe775be6 | |
| 
							
							
								 | 
						563c246329 | |
| 
							
							
								 | 
						7a970e3170 | |
| 
							
							
								 | 
						9a4cc7dd38 | |
| 
							
							
								 | 
						b33606718c | |
| 
							
							
								 | 
						89f5fab97c | |
| 
							
							
								 | 
						ca25a3ee0b | |
| 
							
							
								 | 
						a7e48f3c06 | |
| 
							
							
								 | 
						8f39d5698d | |
| 
							
							
								 | 
						3f9b48ae5f | |
| 
							
							
								 | 
						23165d7bb2 | |
| 
							
							
								 | 
						16e88c6b93 | |
| 
							
							
								 | 
						79034d4f39 | |
| 
							
							
								 | 
						eac9fcd268 | |
| 
							
							
								 | 
						addbb09bf8 | |
| 
							
							
								 | 
						f396351704 | |
| 
							
							
								 | 
						499f5045dd | |
| 
							
							
								 | 
						972398f471 | |
| 
							
							
								 | 
						23eeac46ed | |
| 
							
							
								 | 
						aa0979482f | |
| 
							
							
								 | 
						a299a95413 | |
| 
							
							
								 | 
						64aa214a22 | |
| 
							
							
								 | 
						b8278e0943 | |
| 
							
							
								 | 
						751ba4c8ed | |
| 
							
							
								 | 
						57a88297dd | |
| 
							
							
								 | 
						6f63b1ee67 | |
| 
							
							
								 | 
						241c03029d | |
| 
							
							
								 | 
						928560e6f5 | |
| 
							
							
								 | 
						309bb27ee4 | |
| 
							
							
								 | 
						11e3a56380 | |
| 
							
							
								 | 
						793e9963b8 | |
| 
							
							
								 | 
						3347fe26a0 | |
| 
							
							
								 | 
						93b5cd6919 | |
| 
							
							
								 | 
						2da5c95f3d | |
| 
							
							
								 | 
						aedbf89d85 | |
| 
							
							
								 | 
						08eba2d301 | |
| 
							
							
								 | 
						6a821db6f2 | |
| 
							
							
								 | 
						0306ae30b6 | |
| 
							
							
								 | 
						b04cbd0ba3 | |
| 
							
							
								 | 
						8eadb70a37 | |
| 
							
							
								 | 
						e4924d752b | |
| 
							
							
								 | 
						fe535a89c9 | |
| 
							
							
								 | 
						4072d5b42f | |
| 
							
							
								 | 
						f62c2ad65d | |
| 
							
							
								 | 
						b65adcedb8 | |
| 
							
							
								 | 
						fc69eecca0 | |
| 
							
							
								 | 
						1674225a2f | |
| 
							
							
								 | 
						e93ca8a4d6 | |
| 
							
							
								 | 
						b0e80e9aa9 | |
| 
							
							
								 | 
						56e9672b11 | |
| 
							
							
								 | 
						0d1c51f57f | |
| 
							
							
								 | 
						f6051b9eca | |
| 
							
							
								 | 
						051e4beb79 | |
| 
							
							
								 | 
						8e2fd23acb | |
| 
							
							
								 | 
						755eb22156 | |
| 
							
							
								 | 
						05b0cc416f | |
| 
							
							
								 | 
						71f2000bfb | |
| 
							
							
								 | 
						f6c685e4d3 | |
| 
							
							
								 | 
						7ee8511be4 | |
| 
							
							
								 | 
						f129014ca4 | |
| 
							
							
								 | 
						da6f107eff | |
| 
							
							
								 | 
						d3ec7035bc | |
| 
							
							
								 | 
						a21fef07b6 | |
| 
							
							
								 | 
						603643fa71 | |
| 
							
							
								 | 
						d8fb599c67 | |
| 
							
							
								 | 
						724b4945d5 | |
| 
							
							
								 | 
						2498512972 | |
| 
							
							
								 | 
						d3f14af7ed | |
| 
							
							
								 | 
						04069272b4 | |
| 
							
							
								 | 
						be702d16d0 | |
| 
							
							
								 | 
						6deb361bbf | |
| 
							
							
								 | 
						ab8df2b1a6 | |
| 
							
							
								 | 
						8f484ca78e | |
| 
							
							
								 | 
						12f62ce620 | |
| 
							
							
								 | 
						16a1dca4ad | |
| 
							
							
								 | 
						be10b96d40 | |
| 
							
							
								 | 
						95983cc3fe | |
| 
							
							
								 | 
						11e3319656 | |
| 
							
							
								 | 
						3b2b703177 | |
| 
							
							
								 | 
						87f56d0178 | |
| 
							
							
								 | 
						af2f9a5d85 | |
| 
							
							
								 | 
						5089a14345 | |
| 
							
							
								 | 
						6a25fa4238 | |
| 
							
							
								 | 
						be61937929 | |
| 
							
							
								 | 
						bbcffe51d2 | |
| 
							
							
								 | 
						8e45ba3f4e | |
| 
							
							
								 | 
						fb1d341d6e | |
| 
							
							
								 | 
						42d14d9108 | |
| 
							
							
								 | 
						6c1a4cb44c | |
| 
							
							
								 | 
						56c8dd821e | |
| 
							
							
								 | 
						f9bc17d4c0 | |
| 
							
							
								 | 
						51d64bf501 | |
| 
							
							
								 | 
						c108ef087e | |
| 
							
							
								 | 
						767d4f37c7 | |
| 
							
							
								 | 
						5a01d09482 | |
| 
							
							
								 | 
						6605f1b9bb | |
| 
							
							
								 | 
						bd70ec4b73 | |
| 
							
							
								 | 
						41802ca4c0 | |
| 
							
							
								 | 
						b2e9b6d48a | |
| 
							
							
								 | 
						75696630c1 | |
| 
							
							
								 | 
						f19fc2af33 | |
| 
							
							
								 | 
						157fd444e9 | |
| 
							
							
								 | 
						d2a7e9bf08 | |
| 
							
							
								 | 
						7c517d02f7 | |
| 
							
							
								 | 
						4f0463a079 | |
| 
							
							
								 | 
						688e44ae06 | |
| 
							
							
								 | 
						2472271e08 | |
| 
							
							
								 | 
						b76a414d51 | |
| 
							
							
								 | 
						0b7c07850c | |
| 
							
							
								 | 
						ae32859759 | |
| 
							
							
								 | 
						767ca13532 | |
| 
							
							
								 | 
						e0b6855bd4 | |
| 
							
							
								 | 
						86f76e6cae | |
| 
							
							
								 | 
						6e9606dbae | |
| 
							
							
								 | 
						095eba19d6 | |
| 
							
							
								 | 
						79100d4e8b | |
| 
							
							
								 | 
						5000c12f57 | |
| 
							
							
								 | 
						952c7376e4 | |
| 
							
							
								 | 
						e7d2cd1e05 | |
| 
							
							
								 | 
						6158728cdb | |
| 
							
							
								 | 
						47bbc4b531 | |
| 
							
							
								 | 
						f55bea7626 | |
| 
							
							
								 | 
						b7602846fd | |
| 
							
							
								 | 
						55584d38dd | |
| 
							
							
								 | 
						cb17f580b9 | |
| 
							
							
								 | 
						f82525e60d | |
| 
							
							
								 | 
						00f2e9bc6b | |
| 
							
							
								 | 
						a31010b3e4 | |
| 
							
							
								 | 
						ca0d1a21af | |
| 
							
							
								 | 
						3124d3bc48 | |
| 
							
							
								 | 
						f154b40ddd | |
| 
							
							
								 | 
						a486fca9e2 | |
| 
							
							
								 | 
						f955ffe83f | |
| 
							
							
								 | 
						d6f20d0366 | |
| 
							
							
								 | 
						f7d7ee82dd | |
| 
							
							
								 | 
						9b2b3ef93e | |
| 
							
							
								 | 
						0bca2e75f5 | |
| 
							
							
								 | 
						88d2037bca | |
| 
							
							
								 | 
						e71062d99b | |
| 
							
							
								 | 
						55f26c42de | |
| 
							
							
								 | 
						713f3f8480 | |
| 
							
							
								 | 
						6eab3021ec | |
| 
							
							
								 | 
						1f488f50b9 | |
| 
							
							
								 | 
						41c47f2c6a | |
| 
							
							
								 | 
						f05600f4be | |
| 
							
							
								 | 
						16d4c982a3 | |
| 
							
							
								 | 
						9f58023066 | |
| 
							
							
								 | 
						b7a3d79e46 | |
| 
							
							
								 | 
						b23ecd6ce7 | |
| 
							
							
								 | 
						689749b741 | |
| 
							
							
								 | 
						19c9b17648 | |
| 
							
							
								 | 
						86a1571135 | |
| 
							
							
								 | 
						57837aeda5 | |
| 
							
							
								 | 
						fcc73918b0 | |
| 
							
							
								 | 
						eea576077b | |
| 
							
							
								 | 
						bc98407b8f | |
| 
							
							
								 | 
						7bf81cb7a9 | |
| 
							
							
								 | 
						393375e1fe | |
| 
							
							
								 | 
						9014d45968 | |
| 
							
							
								 | 
						9520fd4134 | |
| 
							
							
								 | 
						6508294dca | |
| 
							
							
								 | 
						5753d2e84b | |
| 
							
							
								 | 
						503519b70a | |
| 
							
							
								 | 
						12788e7e40 | |
| 
							
							
								 | 
						1503d4571b | |
| 
							
							
								 | 
						dde0175d19 | |
| 
							
							
								 | 
						379e95c587 | |
| 
							
							
								 | 
						b5df922e4f | |
| 
							
							
								 | 
						c911599da7 | |
| 
							
							
								 | 
						d2391b5453 | |
| 
							
							
								 | 
						8ebad34370 | |
| 
							
							
								 | 
						db85496ed1 | |
| 
							
							
								 | 
						3782e57129 | |
| 
							
							
								 | 
						612336970d | |
| 
							
							
								 | 
						fcd6a8bdf1 | |
| 
							
							
								 | 
						d1ac53ccd5 | |
| 
							
							
								 | 
						b3fd09937c | |
| 
							
							
								 | 
						bd633efa32 | |
| 
							
							
								 | 
						76f0fa5dfb | |
| 
							
							
								 | 
						692716f5d1 | |
| 
							
							
								 | 
						373e92a491 | |
| 
							
							
								 | 
						21fe5dba36 | |
| 
							
							
								 | 
						e124cf9b7a | |
| 
							
							
								 | 
						efad7cccec | |
| 
							
							
								 | 
						758906aa71 | |
| 
							
							
								 | 
						50ccb36f20 | |
| 
							
							
								 | 
						697fb6ddfc | |
| 
							
							
								 | 
						94e64a0b89 | |
| 
							
							
								 | 
						87dc541027 | |
| 
							
							
								 | 
						00ed77f27c | |
| 
							
							
								 | 
						95c1fe62f7 | |
| 
							
							
								 | 
						9fb9afb573 | |
| 
							
							
								 | 
						43995cda36 | |
| 
							
							
								 | 
						a162eeb2e8 | |
| 
							
							
								 | 
						dd7a72ea69 | |
| 
							
							
								 | 
						58ffcf9712 | |
| 
							
							
								 | 
						8dacbcf68f | |
| 
							
							
								 | 
						f272d7ddc0 | |
| 
							
							
								 | 
						b15ff1c92a | |
| 
							
							
								 | 
						f8195cb2da | |
| 
							
							
								 | 
						76d10d1324 | |
| 
							
							
								 | 
						9e411f4be8 | |
| 
							
							
								 | 
						0f8bee7162 | |
| 
							
							
								 | 
						396cdca0c3 | |
| 
							
							
								 | 
						53012da658 | |
| 
							
							
								 | 
						105df67463 | |
| 
							
							
								 | 
						7bc3cfe6ff | |
| 
							
							
								 | 
						bcee129962 | |
| 
							
							
								 | 
						54d471f498 | |
| 
							
							
								 | 
						463160cbca | |
| 
							
							
								 | 
						db944f1622 | |
| 
							
							
								 | 
						6b82c3e57a | |
| 
							
							
								 | 
						4b25cbffa1 | |
| 
							
							
								 | 
						ca314e060f | |
| 
							
							
								 | 
						c8e789fa0c | |
| 
							
							
								 | 
						31bdc10ec2 | |
| 
							
							
								 | 
						b258c09f26 | |
| 
							
							
								 | 
						05199c0ac9 | |
| 
							
							
								 | 
						55fb76b348 | |
| 
							
							
								 | 
						e66d1892d0 | |
| 
							
							
								 | 
						13d2ac54f4 | |
| 
							
							
								 | 
						f2b8a31be5 | |
| 
							
							
								 | 
						da39089014 | |
| 
							
							
								 | 
						f1aca068c7 | |
| 
							
							
								 | 
						a9010323dd | |
| 
							
							
								 | 
						b4fde527b6 | |
| 
							
							
								 | 
						029b20425b | |
| 
							
							
								 | 
						3553451f1e | |
| 
							
							
								 | 
						8bf18daabb | |
| 
							
							
								 | 
						53279f13e4 | |
| 
							
							
								 | 
						f778bf02ea | |
| 
							
							
								 | 
						6e43c3d531 | |
| 
							
							
								 | 
						4d67b9d9dc | |
| 
							
							
								 | 
						91057d2fc2 | |
| 
							
							
								 | 
						12852b0337 | |
| 
							
							
								 | 
						e374786753 | |
| 
							
							
								 | 
						f1ba6b4b2c | |
| 
							
							
								 | 
						7e46362338 | |
| 
							
							
								 | 
						6402c37916 | |
| 
							
							
								 | 
						093e1cba6b | |
| 
							
							
								 | 
						89ab9fc39c | |
| 
							
							
								 | 
						c3cd66a00c | |
| 
							
							
								 | 
						f670835f1f | |
| 
							
							
								 | 
						d2f7c417fd | |
| 
							
							
								 | 
						6ad2fbaad2 | |
| 
							
							
								 | 
						895cbcdd3c | |
| 
							
							
								 | 
						8b9fa09859 | |
| 
							
							
								 | 
						f97c159536 | |
| 
							
							
								 | 
						b0e1a1ecc4 | |
| 
							
							
								 | 
						fbbafc6909 | |
| 
							
							
								 | 
						b605edf38f | |
| 
							
							
								 | 
						bb0c52719e | |
| 
							
							
								 | 
						b6189f7c8a | |
| 
							
							
								 | 
						ca7d19b5c8 | |
| 
							
							
								 | 
						a8e913c452 | |
| 
							
							
								 | 
						1f4f98e05c | |
| 
							
							
								 | 
						ac9534f48a | |
| 
							
							
								 | 
						7bcf21683e | |
| 
							
							
								 | 
						ad466f86cc | |
| 
							
							
								 | 
						e7eb29685c | |
| 
							
							
								 | 
						61a6d983bd | |
| 
							
							
								 | 
						276d7b18bb | |
| 
							
							
								 | 
						317c97bebb | |
| 
							
							
								 | 
						1a14a62349 | |
| 
							
							
								 | 
						41b8fca1a1 | |
| 
							
							
								 | 
						4a465510fb | |
| 
							
							
								 | 
						1b7b72d49e | |
| 
							
							
								 | 
						01f2adb07a | |
| 
							
							
								 | 
						d114464551 | |
| 
							
							
								 | 
						d91d0b1250 | |
| 
							
							
								 | 
						f1c79a6a35 | |
| 
							
							
								 | 
						ecadb11845 | |
| 
							
							
								 | 
						4984ca28f7 | |
| 
							
							
								 | 
						7962b129c3 | |
| 
							
							
								 | 
						44b46d7036 | |
| 
							
							
								 | 
						f74485b608 | |
| 
							
							
								 | 
						03a0002ed4 | |
| 
							
							
								 | 
						6dfa2c39bf | |
| 
							
							
								 | 
						5e23d42f07 | |
| 
							
							
								 | 
						5e7e327ac8 | |
| 
							
							
								 | 
						658caaf0d1 | |
| 
							
							
								 | 
						4bd770f56b | |
| 
							
							
								 | 
						b0acb693f9 | |
| 
							
							
								 | 
						2f3cf5c21d | |
| 
							
							
								 | 
						731fcfb456 | |
| 
							
							
								 | 
						1ee7074616 | |
| 
							
							
								 | 
						3c749da174 | |
| 
							
							
								 | 
						84f6d40a11 | |
| 
							
							
								 | 
						780c5e2466 | |
| 
							
							
								 | 
						6c317a8d75 | |
| 
							
							
								 | 
						3566348b92 | |
| 
							
							
								 | 
						adcb9951f8 | |
| 
							
							
								 | 
						69f7d9b4a9 | |
| 
							
							
								 | 
						e40ee26b45 | |
| 
							
							
								 | 
						cf398cc058 | |
| 
							
							
								 | 
						cd189a44f8 | |
| 
							
							
								 | 
						c2f35321b3 | |
| 
							
							
								 | 
						ac0facf4e0 | |
| 
							
							
								 | 
						9d71f81532 | |
| 
							
							
								 | 
						9082b5ccf7 | |
| 
							
							
								 | 
						c33f32a922 | |
| 
							
							
								 | 
						a7600dc5c7 | 
| 
						 | 
					@ -8,10 +8,13 @@
 | 
				
			||||||
/configure.lineno
 | 
					/configure.lineno
 | 
				
			||||||
/m4/libtool.m4
 | 
					/m4/libtool.m4
 | 
				
			||||||
/m4/lt*.m4
 | 
					/m4/lt*.m4
 | 
				
			||||||
 | 
					/build
 | 
				
			||||||
 | 
					/inst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Editor/IDE cruft
 | 
					# Editor/IDE cruft
 | 
				
			||||||
*.kate-swp
 | 
					*.kate-swp
 | 
				
			||||||
*~
 | 
					*~
 | 
				
			||||||
 | 
					.*.sw*
 | 
				
			||||||
/*.kdev4
 | 
					/*.kdev4
 | 
				
			||||||
/Makefile.am.user
 | 
					/Makefile.am.user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										9
									
								
								HACKING
								
								
								
								
							
							
						
						
									
										9
									
								
								HACKING
								
								
								
								
							| 
						 | 
					@ -61,8 +61,9 @@ This is a rough overview of what you need to do in order to add a new driver
 | 
				
			||||||
(using the Tondaj SL-814 device as example). It's basically what the
 | 
					(using the Tondaj SL-814 device as example). It's basically what the
 | 
				
			||||||
'new-driver' script (see above) does for you:
 | 
					'new-driver' script (see above) does for you:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - Makefile.am: Add HW_TONDAJ_SL_814 and add to libsigrok_la_SOURCES.
 | 
					 - Makefile.am: Add to src_libdrivers_la_SOURCES under the HW_TONDAJ_SL_814
 | 
				
			||||||
 - configure.ac: Add a DRIVER() and DRIVER2() call.
 | 
					   condition.
 | 
				
			||||||
 | 
					 - configure.ac: Add an SR_DRIVER() call.
 | 
				
			||||||
 - src/drivers.c: Add a tondaj_sl_814_driver_info entry in two places.
 | 
					 - src/drivers.c: Add a tondaj_sl_814_driver_info entry in two places.
 | 
				
			||||||
 - src/hardware/tondaj-sl-814/ directory: Add api.c, protocol.c, protocol.h.
 | 
					 - src/hardware/tondaj-sl-814/ directory: Add api.c, protocol.c, protocol.h.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,7 +164,9 @@ Doxygen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - Mark private functions (SR_PRIV) with /** @private */, so that Doxygen
 | 
					 - Mark private functions (SR_PRIV) with /** @private */, so that Doxygen
 | 
				
			||||||
   doesn't include them in the output. Functions that are "static" anyway
 | 
					   doesn't include them in the output. Functions that are "static" anyway
 | 
				
			||||||
   don't need to be marked like this.
 | 
					   don't need to be marked like this. Functions in non-public files that
 | 
				
			||||||
 | 
					   are explicitly excluded in Doxyfile don't need to be marked either.
 | 
				
			||||||
 | 
					   Don't use @internal, always use @private instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - Mark private variables/#defines with /** @cond PRIVATE */ and
 | 
					 - Mark private variables/#defines with /** @cond PRIVATE */ and
 | 
				
			||||||
   /** @endcond */, so that Doxygen doesn't include them in the output.
 | 
					   /** @endcond */, so that Doxygen doesn't include them in the output.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										250
									
								
								Makefile.am
								
								
								
								
							
							
						
						
									
										250
									
								
								Makefile.am
								
								
								
								
							| 
						 | 
					@ -27,7 +27,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FIRMWARE_DIR = $(datadir)/sigrok-firmware
 | 
					FIRMWARE_DIR = $(datadir)/sigrok-firmware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local_includes = -Iinclude -I$(srcdir)/include -I$(srcdir)/src -I.
 | 
					local_includes = -Iinclude -I$(srcdir)/include -I$(srcdir)/src -I. @RPC_CFLAGS@
 | 
				
			||||||
if BINDINGS_CXX
 | 
					if BINDINGS_CXX
 | 
				
			||||||
local_includes += -Ibindings/cxx/include -I$(srcdir)/bindings/cxx/include -Ibindings/cxx
 | 
					local_includes += -Ibindings/cxx/include -I$(srcdir)/bindings/cxx/include -Ibindings/cxx
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,9 @@ lib_LTLIBRARIES = libsigrok.la
 | 
				
			||||||
# Backend files
 | 
					# Backend files
 | 
				
			||||||
libsigrok_la_SOURCES = \
 | 
					libsigrok_la_SOURCES = \
 | 
				
			||||||
	src/backend.c \
 | 
						src/backend.c \
 | 
				
			||||||
 | 
						src/binary_helpers.c \
 | 
				
			||||||
 | 
						src/conversion.c \
 | 
				
			||||||
 | 
						src/crc.c \
 | 
				
			||||||
	src/device.c \
 | 
						src/device.c \
 | 
				
			||||||
	src/session.c \
 | 
						src/session.c \
 | 
				
			||||||
	src/session_file.c \
 | 
						src/session_file.c \
 | 
				
			||||||
| 
						 | 
					@ -70,13 +73,17 @@ libsigrok_la_SOURCES = \
 | 
				
			||||||
# Input modules
 | 
					# Input modules
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/input/input.c \
 | 
						src/input/input.c \
 | 
				
			||||||
 | 
						src/input/feed_queue.c \
 | 
				
			||||||
	src/input/binary.c \
 | 
						src/input/binary.c \
 | 
				
			||||||
	src/input/chronovu_la8.c \
 | 
						src/input/chronovu_la8.c \
 | 
				
			||||||
	src/input/csv.c \
 | 
						src/input/csv.c \
 | 
				
			||||||
 | 
						src/input/logicport.c \
 | 
				
			||||||
	src/input/raw_analog.c \
 | 
						src/input/raw_analog.c \
 | 
				
			||||||
 | 
						src/input/saleae.c \
 | 
				
			||||||
	src/input/trace32_ad.c \
 | 
						src/input/trace32_ad.c \
 | 
				
			||||||
	src/input/vcd.c \
 | 
						src/input/vcd.c \
 | 
				
			||||||
	src/input/wav.c
 | 
						src/input/wav.c \
 | 
				
			||||||
 | 
						src/input/null.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Output modules
 | 
					# Output modules
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
| 
						 | 
					@ -91,7 +98,9 @@ libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/output/hex.c \
 | 
						src/output/hex.c \
 | 
				
			||||||
	src/output/ols.c \
 | 
						src/output/ols.c \
 | 
				
			||||||
	src/output/srzip.c \
 | 
						src/output/srzip.c \
 | 
				
			||||||
	src/output/vcd.c
 | 
						src/output/vcd.c \
 | 
				
			||||||
 | 
						src/output/wavedrom.c \
 | 
				
			||||||
 | 
						src/output/null.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Transform modules
 | 
					# Transform modules
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
| 
						 | 
					@ -104,7 +113,6 @@ libsigrok_la_SOURCES += \
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/scpi.h \
 | 
						src/scpi.h \
 | 
				
			||||||
	src/scpi/scpi.c \
 | 
						src/scpi/scpi.c \
 | 
				
			||||||
	src/scpi/helpers.c \
 | 
					 | 
				
			||||||
	src/scpi/scpi_tcp.c
 | 
						src/scpi/scpi_tcp.c
 | 
				
			||||||
if NEED_RPC
 | 
					if NEED_RPC
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
| 
						 | 
					@ -113,9 +121,21 @@ libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/scpi/vxi_xdr.c \
 | 
						src/scpi/vxi_xdr.c \
 | 
				
			||||||
	src/scpi/vxi.h
 | 
						src/scpi/vxi.h
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					# if HAVE_BLUETOOTH
 | 
				
			||||||
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
 | 
						src/bt/bt_bluez.c
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
if NEED_SERIAL
 | 
					if NEED_SERIAL
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/serial.c \
 | 
						src/serial.c \
 | 
				
			||||||
 | 
						src/serial_bt.c \
 | 
				
			||||||
 | 
						src/serial_hid.c \
 | 
				
			||||||
 | 
						src/serial_hid.h \
 | 
				
			||||||
 | 
						src/serial_hid_bu86x.c \
 | 
				
			||||||
 | 
						src/serial_hid_ch9325.c \
 | 
				
			||||||
 | 
						src/serial_hid_cp2110.c \
 | 
				
			||||||
 | 
						src/serial_hid_victor.c \
 | 
				
			||||||
 | 
						src/serial_libsp.c \
 | 
				
			||||||
	src/scpi/scpi_serial.c
 | 
						src/scpi/scpi_serial.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
if NEED_USB
 | 
					if NEED_USB
 | 
				
			||||||
| 
						 | 
					@ -143,23 +163,32 @@ endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hardware (DMM chip parsers)
 | 
					# Hardware (DMM chip parsers)
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
 | 
						src/dmm/asycii.c \
 | 
				
			||||||
 | 
						src/dmm/bm25x.c \
 | 
				
			||||||
 | 
						src/dmm/bm52x.c \
 | 
				
			||||||
 | 
						src/dmm/bm85x.c \
 | 
				
			||||||
 | 
						src/dmm/bm86x.c \
 | 
				
			||||||
 | 
						src/dmm/dtm0660.c \
 | 
				
			||||||
 | 
						src/dmm/eev121gw.c \
 | 
				
			||||||
	src/dmm/es519xx.c \
 | 
						src/dmm/es519xx.c \
 | 
				
			||||||
	src/dmm/fs9721.c \
 | 
						src/dmm/fs9721.c \
 | 
				
			||||||
	src/dmm/fs9922.c \
 | 
						src/dmm/fs9922.c \
 | 
				
			||||||
	src/dmm/m2110.c \
 | 
						src/dmm/m2110.c \
 | 
				
			||||||
	src/dmm/metex14.c \
 | 
						src/dmm/metex14.c \
 | 
				
			||||||
	src/dmm/asycii.c \
 | 
						src/dmm/mm38xr.c \
 | 
				
			||||||
 | 
						src/dmm/ms2115b.c \
 | 
				
			||||||
 | 
						src/dmm/ms8250d.c \
 | 
				
			||||||
	src/dmm/rs9lcd.c \
 | 
						src/dmm/rs9lcd.c \
 | 
				
			||||||
	src/dmm/bm25x.c \
 | 
					 | 
				
			||||||
	src/dmm/ut71x.c \
 | 
					 | 
				
			||||||
	src/dmm/ut372.c \
 | 
						src/dmm/ut372.c \
 | 
				
			||||||
 | 
						src/dmm/ut71x.c \
 | 
				
			||||||
	src/dmm/vc870.c \
 | 
						src/dmm/vc870.c \
 | 
				
			||||||
	src/dmm/dtm0660.c
 | 
						src/dmm/vc96.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hardware (LCR chip parsers)
 | 
					# Hardware (LCR chip parsers)
 | 
				
			||||||
if NEED_SERIAL
 | 
					if NEED_SERIAL
 | 
				
			||||||
libsigrok_la_SOURCES += \
 | 
					libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/lcr/es51919.c
 | 
						src/lcr/es51919.c \
 | 
				
			||||||
 | 
						src/lcr/vc4080.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hardware (Scale protocol parsers)
 | 
					# Hardware (Scale protocol parsers)
 | 
				
			||||||
| 
						 | 
					@ -167,15 +196,22 @@ libsigrok_la_SOURCES += \
 | 
				
			||||||
	src/scale/kern.c
 | 
						src/scale/kern.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Hardware drivers
 | 
					# Hardware drivers
 | 
				
			||||||
noinst_LTLIBRARIES = src/libdrivers.la
 | 
					noinst_LTLIBRARIES = src/libdrivers.la \
 | 
				
			||||||
 | 
						src/libdrivers_head.la src/libdrivers_tail.la
 | 
				
			||||||
 | 
					
 | 
				
			||||||
src/libdrivers.o: src/libdrivers.la
 | 
					src/libdrivers.o: src/libdrivers.la \
 | 
				
			||||||
	$(AM_V_CCLD)$(LINK) src/libdrivers.la
 | 
							src/libdrivers_head.la src/libdrivers_tail.la
 | 
				
			||||||
 | 
						$(AM_V_CCLD)$(LINK) src/libdrivers_head.la src/libdrivers.la \
 | 
				
			||||||
 | 
							src/libdrivers_tail.la
 | 
				
			||||||
src/libdrivers.lo: src/libdrivers.o
 | 
					src/libdrivers.lo: src/libdrivers.o
 | 
				
			||||||
	$(AM_V_GEN)echo "# Generated by libtool" > $@
 | 
						$(AM_V_GEN)echo "# Generated by libtool" > $@
 | 
				
			||||||
	$(AM_V_at)echo "pic_object='libdrivers.o'" >> $@
 | 
						$(AM_V_at)echo "pic_object='libdrivers.o'" >> $@
 | 
				
			||||||
	$(AM_V_at)echo "non_pic_object='libdrivers.o'" >> $@
 | 
						$(AM_V_at)echo "non_pic_object='libdrivers.o'" >> $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					src_libdrivers_head_la_SOURCES = src/driver_list_start.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					src_libdrivers_tail_la_SOURCES = src/driver_list_stop.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
src_libdrivers_la_SOURCES = src/drivers.c
 | 
					src_libdrivers_la_SOURCES = src/drivers.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if HW_AGILENT_DMM
 | 
					if HW_AGILENT_DMM
 | 
				
			||||||
| 
						 | 
					@ -221,20 +257,9 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/beaglelogic/beaglelogic.h \
 | 
						src/hardware/beaglelogic/beaglelogic.h \
 | 
				
			||||||
	src/hardware/beaglelogic/protocol.h \
 | 
						src/hardware/beaglelogic/protocol.h \
 | 
				
			||||||
	src/hardware/beaglelogic/protocol.c \
 | 
						src/hardware/beaglelogic/protocol.c \
 | 
				
			||||||
	src/hardware/beaglelogic/api.c
 | 
						src/hardware/beaglelogic/api.c \
 | 
				
			||||||
endif
 | 
						src/hardware/beaglelogic/beaglelogic_native.c \
 | 
				
			||||||
if HW_BRYMEN_BM86X
 | 
						src/hardware/beaglelogic/beaglelogic_tcp.c
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					 | 
				
			||||||
	src/hardware/brymen-bm86x/protocol.h \
 | 
					 | 
				
			||||||
	src/hardware/brymen-bm86x/protocol.c \
 | 
					 | 
				
			||||||
	src/hardware/brymen-bm86x/api.c
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
if HW_BRYMEN_DMM
 | 
					 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					 | 
				
			||||||
	src/hardware/brymen-dmm/parser.c \
 | 
					 | 
				
			||||||
	src/hardware/brymen-dmm/protocol.h \
 | 
					 | 
				
			||||||
	src/hardware/brymen-dmm/protocol.c \
 | 
					 | 
				
			||||||
	src/hardware/brymen-dmm/api.c
 | 
					 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
if HW_CEM_DT_885X
 | 
					if HW_CEM_DT_885X
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
| 
						 | 
					@ -266,12 +291,30 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/conrad-digi-35-cpu/protocol.c \
 | 
						src/hardware/conrad-digi-35-cpu/protocol.c \
 | 
				
			||||||
	src/hardware/conrad-digi-35-cpu/api.c
 | 
						src/hardware/conrad-digi-35-cpu/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_DCTTECH_USBRELAY
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/dcttech-usbrelay/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/dcttech-usbrelay/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/dcttech-usbrelay/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_DEMO
 | 
					if HW_DEMO
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/demo/protocol.h \
 | 
						src/hardware/demo/protocol.h \
 | 
				
			||||||
	src/hardware/demo/protocol.c \
 | 
						src/hardware/demo/protocol.c \
 | 
				
			||||||
	src/hardware/demo/api.c
 | 
						src/hardware/demo/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_DREAMSOURCELAB_DSLOGIC
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/dreamsourcelab-dslogic/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/dreamsourcelab-dslogic/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/dreamsourcelab-dslogic/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_FLUKE_45
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/fluke-45/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/fluke-45/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/fluke-45/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_FLUKE_DMM
 | 
					if HW_FLUKE_DMM
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/fluke-dmm/protocol.h \
 | 
						src/hardware/fluke-dmm/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -288,9 +331,7 @@ if HW_FX2LAFW
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/fx2lafw/protocol.h \
 | 
						src/hardware/fx2lafw/protocol.h \
 | 
				
			||||||
	src/hardware/fx2lafw/protocol.c \
 | 
						src/hardware/fx2lafw/protocol.c \
 | 
				
			||||||
	src/hardware/fx2lafw/api.c \
 | 
						src/hardware/fx2lafw/api.c
 | 
				
			||||||
	src/hardware/fx2lafw/dslogic.c \
 | 
					 | 
				
			||||||
	src/hardware/fx2lafw/dslogic.h
 | 
					 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
if HW_GMC_MH_1X_2X
 | 
					if HW_GMC_MH_1X_2X
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
| 
						 | 
					@ -304,12 +345,24 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/gwinstek-gds-800/protocol.c \
 | 
						src/hardware/gwinstek-gds-800/protocol.c \
 | 
				
			||||||
	src/hardware/gwinstek-gds-800/api.c
 | 
						src/hardware/gwinstek-gds-800/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_GWINSTEK_GPD
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/gwinstek-gpd/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/gwinstek-gpd/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/gwinstek-gpd/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_HAMEG_HMO
 | 
					if HW_HAMEG_HMO
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/hameg-hmo/protocol.h \
 | 
						src/hardware/hameg-hmo/protocol.h \
 | 
				
			||||||
	src/hardware/hameg-hmo/protocol.c \
 | 
						src/hardware/hameg-hmo/protocol.c \
 | 
				
			||||||
	src/hardware/hameg-hmo/api.c
 | 
						src/hardware/hameg-hmo/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_HANTEK_4032L
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/hantek-4032l/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/hantek-4032l/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/hantek-4032l/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_HANTEK_6XXX
 | 
					if HW_HANTEK_6XXX
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/hantek-6xxx/protocol.h \
 | 
						src/hardware/hantek-6xxx/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -328,6 +381,18 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/hp-3457a/protocol.c \
 | 
						src/hardware/hp-3457a/protocol.c \
 | 
				
			||||||
	src/hardware/hp-3457a/api.c
 | 
						src/hardware/hp-3457a/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_HP_3478A
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/hp-3478a/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/hp-3478a/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/hp-3478a/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_HP_59306A
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/hp-59306a/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/hp-59306a/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/hp-59306a/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_HUNG_CHANG_DSO_2100
 | 
					if HW_HUNG_CHANG_DSO_2100
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/hung-chang-dso-2100/protocol.h \
 | 
						src/hardware/hung-chang-dso-2100/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -346,6 +411,24 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/ikalogic-scanaplus/protocol.c \
 | 
						src/hardware/ikalogic-scanaplus/protocol.c \
 | 
				
			||||||
	src/hardware/ikalogic-scanaplus/api.c
 | 
						src/hardware/ikalogic-scanaplus/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_IKALOGIC_SCANAQUAD
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/ikalogic-scanaquad/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/ikalogic-scanaquad/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/ikalogic-scanaquad/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_IPDBG_LA
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/ipdbg-la/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/ipdbg-la/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/ipdbg-la/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_ITECH_IT8500
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/itech-it8500/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/itech-it8500/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/itech-it8500/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_KECHENG_KC_330B
 | 
					if HW_KECHENG_KC_330B
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/kecheng-kc-330b/protocol.h \
 | 
						src/hardware/kecheng-kc-330b/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -358,6 +441,12 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/kern-scale/protocol.c \
 | 
						src/hardware/kern-scale/protocol.c \
 | 
				
			||||||
	src/hardware/kern-scale/api.c
 | 
						src/hardware/kern-scale/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_KINGST_LA2016
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/kingst-la2016/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/kingst-la2016/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/kingst-la2016/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_KORAD_KAXXXXP
 | 
					if HW_KORAD_KAXXXXP
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/korad-kaxxxxp/protocol.h \
 | 
						src/hardware/korad-kaxxxxp/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -388,18 +477,36 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/manson-hcs-3xxx/protocol.c \
 | 
						src/hardware/manson-hcs-3xxx/protocol.c \
 | 
				
			||||||
	src/hardware/manson-hcs-3xxx/api.c
 | 
						src/hardware/manson-hcs-3xxx/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_MASTECH_MS6514
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/mastech-ms6514/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/mastech-ms6514/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/mastech-ms6514/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_MAYNUO_M97
 | 
					if HW_MAYNUO_M97
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/maynuo-m97/protocol.h \
 | 
						src/hardware/maynuo-m97/protocol.h \
 | 
				
			||||||
	src/hardware/maynuo-m97/protocol.c \
 | 
						src/hardware/maynuo-m97/protocol.c \
 | 
				
			||||||
	src/hardware/maynuo-m97/api.c
 | 
						src/hardware/maynuo-m97/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_MICROCHIP_PICKIT2
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/microchip-pickit2/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/microchip-pickit2/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/microchip-pickit2/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_MIC_985XX
 | 
					if HW_MIC_985XX
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/mic-985xx/protocol.h \
 | 
						src/hardware/mic-985xx/protocol.h \
 | 
				
			||||||
	src/hardware/mic-985xx/protocol.c \
 | 
						src/hardware/mic-985xx/protocol.c \
 | 
				
			||||||
	src/hardware/mic-985xx/api.c
 | 
						src/hardware/mic-985xx/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_MOOSHIMETER_DMM
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/mooshimeter-dmm/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/mooshimeter-dmm/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/mooshimeter-dmm/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_MOTECH_LPS_30X
 | 
					if HW_MOTECH_LPS_30X
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/motech-lps-30x/protocol.h \
 | 
						src/hardware/motech-lps-30x/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -430,6 +537,30 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/pipistrello-ols/protocol.c \
 | 
						src/hardware/pipistrello-ols/protocol.c \
 | 
				
			||||||
	src/hardware/pipistrello-ols/api.c
 | 
						src/hardware/pipistrello-ols/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_RDTECH_DPS
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/rdtech-dps/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/rdtech-dps/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/rdtech-dps/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_RDTECH_UM
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/rdtech-um/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/rdtech-um/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/rdtech-um/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_RDTECH_TC
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/rdtech-tc/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/rdtech-tc/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/rdtech-tc/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_RIGOL_DG
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/rigol-dg/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/rigol-dg/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/rigol-dg/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_RIGOL_DS
 | 
					if HW_RIGOL_DS
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/rigol-ds/protocol.h \
 | 
						src/hardware/rigol-ds/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -448,6 +579,18 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/saleae-logic16/protocol.c \
 | 
						src/hardware/saleae-logic16/protocol.c \
 | 
				
			||||||
	src/hardware/saleae-logic16/api.c
 | 
						src/hardware/saleae-logic16/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_SALEAE_LOGIC_PRO
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/saleae-logic-pro/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/saleae-logic-pro/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/saleae-logic-pro/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					if HW_SCPI_DMM
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/scpi-dmm/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/scpi-dmm/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/scpi-dmm/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_SCPI_PPS
 | 
					if HW_SCPI_PPS
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/scpi-pps/protocol.h \
 | 
						src/hardware/scpi-pps/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -463,8 +606,16 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
if HW_SERIAL_LCR
 | 
					if HW_SERIAL_LCR
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/serial-lcr/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/serial-lcr/protocol.c \
 | 
				
			||||||
	src/hardware/serial-lcr/api.c
 | 
						src/hardware/serial-lcr/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_SIGLENT_SDS
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/siglent-sds/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/siglent-sds/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/siglent-sds/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_SYSCLK_LWLA
 | 
					if HW_SYSCLK_LWLA
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/sysclk-lwla/lwla.h \
 | 
						src/hardware/sysclk-lwla/lwla.h \
 | 
				
			||||||
| 
						 | 
					@ -475,6 +626,12 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/sysclk-lwla/protocol.c \
 | 
						src/hardware/sysclk-lwla/protocol.c \
 | 
				
			||||||
	src/hardware/sysclk-lwla/api.c
 | 
						src/hardware/sysclk-lwla/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_SYSCLK_SLA5032
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/sysclk-sla5032/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/sysclk-sla5032/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/sysclk-sla5032/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_TELEINFO
 | 
					if HW_TELEINFO
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/teleinfo/protocol.h \
 | 
						src/hardware/teleinfo/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -499,18 +656,18 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/uni-t-dmm/protocol.c \
 | 
						src/hardware/uni-t-dmm/protocol.c \
 | 
				
			||||||
	src/hardware/uni-t-dmm/api.c
 | 
						src/hardware/uni-t-dmm/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_UNI_T_UT181A
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/uni-t-ut181a/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/uni-t-ut181a/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/uni-t-ut181a/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
if HW_UNI_T_UT32X
 | 
					if HW_UNI_T_UT32X
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/uni-t-ut32x/protocol.h \
 | 
						src/hardware/uni-t-ut32x/protocol.h \
 | 
				
			||||||
	src/hardware/uni-t-ut32x/protocol.c \
 | 
						src/hardware/uni-t-ut32x/protocol.c \
 | 
				
			||||||
	src/hardware/uni-t-ut32x/api.c
 | 
						src/hardware/uni-t-ut32x/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
if HW_VICTOR_DMM
 | 
					 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					 | 
				
			||||||
	src/hardware/victor-dmm/protocol.h \
 | 
					 | 
				
			||||||
	src/hardware/victor-dmm/protocol.c \
 | 
					 | 
				
			||||||
	src/hardware/victor-dmm/api.c
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
if HW_YOKOGAWA_DLM
 | 
					if HW_YOKOGAWA_DLM
 | 
				
			||||||
src_libdrivers_la_SOURCES += \
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/yokogawa-dlm/protocol.h \
 | 
						src/hardware/yokogawa-dlm/protocol.h \
 | 
				
			||||||
| 
						 | 
					@ -529,6 +686,12 @@ src_libdrivers_la_SOURCES += \
 | 
				
			||||||
	src/hardware/zeroplus-logic-cube/protocol.c \
 | 
						src/hardware/zeroplus-logic-cube/protocol.c \
 | 
				
			||||||
	src/hardware/zeroplus-logic-cube/api.c
 | 
						src/hardware/zeroplus-logic-cube/api.c
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					if HW_ZKETECH_EBD_USB
 | 
				
			||||||
 | 
					src_libdrivers_la_SOURCES += \
 | 
				
			||||||
 | 
						src/hardware/zketech-ebd-usb/protocol.h \
 | 
				
			||||||
 | 
						src/hardware/zketech-ebd-usb/protocol.c \
 | 
				
			||||||
 | 
						src/hardware/zketech-ebd-usb/api.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
libsigrok_la_LIBADD = src/libdrivers.lo $(SR_EXTRA_LIBS) $(LIBSIGROK_LIBS)
 | 
					libsigrok_la_LIBADD = src/libdrivers.lo $(SR_EXTRA_LIBS) $(LIBSIGROK_LIBS)
 | 
				
			||||||
libsigrok_la_LDFLAGS = -version-info $(SR_LIB_VERSION) -no-undefined
 | 
					libsigrok_la_LDFLAGS = -version-info $(SR_LIB_VERSION) -no-undefined
 | 
				
			||||||
| 
						 | 
					@ -544,7 +707,7 @@ noinst_HEADERS = src/libsigrok-internal.h
 | 
				
			||||||
pkgconfigdir = $(libdir)/pkgconfig
 | 
					pkgconfigdir = $(libdir)/pkgconfig
 | 
				
			||||||
pkgconfig_DATA = libsigrok.pc
 | 
					pkgconfig_DATA = libsigrok.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mimeappdir = $(datadir)/mime/application
 | 
					mimeappdir = $(datadir)/mime/packages
 | 
				
			||||||
mimeapp_DATA = contrib/vnd.sigrok.session.xml
 | 
					mimeapp_DATA = contrib/vnd.sigrok.session.xml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mimeicondir = $(datadir)/icons/hicolor/48x48/mimetypes
 | 
					mimeicondir = $(datadir)/icons/hicolor/48x48/mimetypes
 | 
				
			||||||
| 
						 | 
					@ -581,7 +744,9 @@ EXTRA_DIST = \
 | 
				
			||||||
	contrib/libsigrok.png \
 | 
						contrib/libsigrok.png \
 | 
				
			||||||
	contrib/libsigrok.svg \
 | 
						contrib/libsigrok.svg \
 | 
				
			||||||
	contrib/vnd.sigrok.session.xml \
 | 
						contrib/vnd.sigrok.session.xml \
 | 
				
			||||||
	contrib/z60_libsigrok.rules
 | 
						contrib/60-libsigrok.rules \
 | 
				
			||||||
 | 
						contrib/61-libsigrok-plugdev.rules \
 | 
				
			||||||
 | 
						contrib/61-libsigrok-uaccess.rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if HAVE_CHECK
 | 
					if HAVE_CHECK
 | 
				
			||||||
TESTS = tests/main
 | 
					TESTS = tests/main
 | 
				
			||||||
| 
						 | 
					@ -604,7 +769,8 @@ tests_main_SOURCES = \
 | 
				
			||||||
	tests/driver_all.c \
 | 
						tests/driver_all.c \
 | 
				
			||||||
	tests/device.c \
 | 
						tests/device.c \
 | 
				
			||||||
	tests/trigger.c \
 | 
						tests/trigger.c \
 | 
				
			||||||
	tests/analog.c
 | 
						tests/analog.c \
 | 
				
			||||||
 | 
						tests/conv.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tests_main_LDADD = libsigrok.la $(SR_EXTRA_LIBS) $(TESTS_LIBS)
 | 
					tests_main_LDADD = libsigrok.la $(SR_EXTRA_LIBS) $(TESTS_LIBS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -636,7 +802,7 @@ nodist_bindings_cxx_libsigrokcxx_la_include_HEADERS = \
 | 
				
			||||||
pkgconfig_DATA += bindings/cxx/libsigrokcxx.pc
 | 
					pkgconfig_DATA += bindings/cxx/libsigrokcxx.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
doxy/xml/index.xml: include/libsigrok/libsigrok.h
 | 
					doxy/xml/index.xml: include/libsigrok/libsigrok.h
 | 
				
			||||||
	$(AM_V_GEN)cd $(srcdir) && BUILDDIR=$(abs_builddir)/ doxygen Doxyfile 2>/dev/null
 | 
						$(AM_V_GEN)cd $(srcdir) && SRCDIR=$(abs_srcdir)/ BUILDDIR=$(abs_builddir)/ doxygen Doxyfile 2>/dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bindings/swig/enums.i: bindings/cxx/enums.timestamp
 | 
					bindings/swig/enums.i: bindings/cxx/enums.timestamp
 | 
				
			||||||
bindings/cxx/enums.cpp: bindings/cxx/enums.timestamp
 | 
					bindings/cxx/enums.cpp: bindings/cxx/enums.timestamp
 | 
				
			||||||
| 
						 | 
					@ -671,7 +837,7 @@ CPPXMLDOC = bindings/cxx/doxy/xml/index.xml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(CPPXMLDOC): bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp \
 | 
					$(CPPXMLDOC): bindings/cxx/include/libsigrokcxx/libsigrokcxx.hpp \
 | 
				
			||||||
		bindings/cxx/enums.timestamp
 | 
							bindings/cxx/enums.timestamp
 | 
				
			||||||
	$(AM_V_GEN)cd $(srcdir)/bindings/cxx && BUILDDIR=$(abs_builddir)/bindings/cxx/ doxygen Doxyfile 2>/dev/null
 | 
						$(AM_V_GEN)cd $(srcdir)/bindings/cxx && SRCDIR=$(abs_srcdir)/bindings/cxx/ BUILDDIR=$(abs_builddir)/bindings/cxx/ doxygen Doxyfile 2>/dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Macro definitions to be used by the SWIG parser.
 | 
					# Macro definitions to be used by the SWIG parser.
 | 
				
			||||||
swig_defs = -Dnoexcept= -Dprivate=protected -DG_GNUC_BEGIN_IGNORE_DEPRECATIONS= -DG_GNUC_END_IGNORE_DEPRECATIONS=
 | 
					swig_defs = -Dnoexcept= -Dprivate=protected -DG_GNUC_BEGIN_IGNORE_DEPRECATIONS= -DG_GNUC_END_IGNORE_DEPRECATIONS=
 | 
				
			||||||
| 
						 | 
					@ -719,7 +885,7 @@ python-clean:
 | 
				
			||||||
	-$(AM_V_at)$(setup_py) clean --all 2>/dev/null
 | 
						-$(AM_V_at)$(setup_py) clean --all 2>/dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
python-doc:
 | 
					python-doc:
 | 
				
			||||||
	$(AM_V_at)cd $(srcdir)/$(PDIR) && BUILDDIR="$(abs_builddir)/$(PDIR)/" doxygen Doxyfile 2>/dev/null
 | 
						$(AM_V_at)cd $(srcdir)/$(PDIR) && SRCDIR="$(abs_srcdir)/$(PDIR)/" BUILDDIR="$(abs_builddir)/$(PDIR)/" doxygen Doxyfile 2>/dev/null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BUILD_EXTRA += python-build
 | 
					BUILD_EXTRA += python-build
 | 
				
			||||||
INSTALL_EXTRA += python-install
 | 
					INSTALL_EXTRA += python-install
 | 
				
			||||||
| 
						 | 
					@ -836,7 +1002,7 @@ java-clean:
 | 
				
			||||||
	-$(AM_V_at)rm -fr $(JDIR)/doxy
 | 
						-$(AM_V_at)rm -fr $(JDIR)/doxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
java-doc:
 | 
					java-doc:
 | 
				
			||||||
	$(AM_V_at)cd $(srcdir)/$(JDIR) && BUILDDIR="$(abs_builddir)/$(JDIR)/" doxygen Doxyfile
 | 
						$(AM_V_at)cd $(srcdir)/$(JDIR) && SRCDIR="$(abs_srcdir)/$(JDIR)/" BUILDDIR="$(abs_builddir)/$(JDIR)/" doxygen Doxyfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BUILD_EXTRA += java-build
 | 
					BUILD_EXTRA += java-build
 | 
				
			||||||
INSTALL_EXTRA += java-install
 | 
					INSTALL_EXTRA += java-install
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								NEWS
								
								
								
								
							
							
						
						
									
										2
									
								
								NEWS
								
								
								
								
							| 
						 | 
					@ -205,7 +205,7 @@ Note: This release DOES change the libsigrok API. That means it is NOT
 | 
				
			||||||
     - LeCroy LogicStudio
 | 
					     - LeCroy LogicStudio
 | 
				
			||||||
     - mcupro Logic16 clone
 | 
					     - mcupro Logic16 clone
 | 
				
			||||||
     - Pipistrello OLS
 | 
					     - Pipistrello OLS
 | 
				
			||||||
     - SysClk LWLA1016
 | 
					     - Sysclk LWLA1016
 | 
				
			||||||
   - Oscilloscopes:
 | 
					   - Oscilloscopes:
 | 
				
			||||||
     - Rigol/Agilent DS1000Z series
 | 
					     - Rigol/Agilent DS1000Z series
 | 
				
			||||||
     - Yokogawa DLM2000 series
 | 
					     - Yokogawa DLM2000 series
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								README
								
								
								
								
							
							
						
						
									
										10
									
								
								README
								
								
								
								
							| 
						 | 
					@ -38,12 +38,16 @@ Requirements for the C library:
 | 
				
			||||||
 - pkg-config >= 0.22
 | 
					 - pkg-config >= 0.22
 | 
				
			||||||
 - libglib >= 2.32.0
 | 
					 - libglib >= 2.32.0
 | 
				
			||||||
 - libzip >= 0.10
 | 
					 - libzip >= 0.10
 | 
				
			||||||
 | 
					 - libtirpc (optional, used by VXI, fallback when glibc >= 2.26)
 | 
				
			||||||
 - libserialport >= 0.1.1 (optional, used by some drivers)
 | 
					 - libserialport >= 0.1.1 (optional, used by some drivers)
 | 
				
			||||||
 - librevisa >= 0.0.20130412 (optional, used by some drivers)
 | 
					 - librevisa >= 0.0.20130412 (optional, used by some drivers)
 | 
				
			||||||
 - libusb-1.0 >= 1.0.16 (optional, used by some drivers)
 | 
					 - libusb-1.0 >= 1.0.16 (optional, used by some drivers)
 | 
				
			||||||
 - libftdi >= 0.16 or libftdi1 >= 1.0 (optional, used by some drivers)
 | 
					 - hidapi >= 0.8.0 (optional, used for some HID based "serial cables")
 | 
				
			||||||
 | 
					 - bluez/libbluetooth >= 4.0 (optional, used for Bluetooth/BLE communication)
 | 
				
			||||||
 | 
					 - libftdi1 >= 1.0 (optional, used by some drivers)
 | 
				
			||||||
 - libgpib (optional, used by some drivers)
 | 
					 - libgpib (optional, used by some drivers)
 | 
				
			||||||
 - libieee1284 (optional, used by some drivers)
 | 
					 - libieee1284 (optional, used by some drivers)
 | 
				
			||||||
 | 
					 - libgio >= 2.32.0 (optional, used by some drivers)
 | 
				
			||||||
 - check >= 0.9.4 (optional, only needed to run unit tests)
 | 
					 - check >= 0.9.4 (optional, only needed to run unit tests)
 | 
				
			||||||
 - doxygen (optional, only needed for the C API docs)
 | 
					 - doxygen (optional, only needed for the C API docs)
 | 
				
			||||||
 - graphviz (optional, only needed for the C API docs)
 | 
					 - graphviz (optional, only needed for the C API docs)
 | 
				
			||||||
| 
						 | 
					@ -75,7 +79,7 @@ Requirements for the Python bindings:
 | 
				
			||||||
Requirements for the Ruby bindings:
 | 
					Requirements for the Ruby bindings:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - libsigrokcxx >= 0.4.0 (the libsigrok C++ bindings, see above)
 | 
					 - libsigrokcxx >= 0.4.0 (the libsigrok C++ bindings, see above)
 | 
				
			||||||
 - Ruby >= 1.9.3 (including development files!)
 | 
					 - Ruby >= 2.5.0 (including development files!)
 | 
				
			||||||
 - SWIG >= 3.0.8
 | 
					 - SWIG >= 3.0.8
 | 
				
			||||||
 - YARD (optional, only needed for the Ruby API docs)
 | 
					 - YARD (optional, only needed for the Ruby API docs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +152,7 @@ Mailing list
 | 
				
			||||||
IRC
 | 
					IRC
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can find the sigrok developers in the #sigrok IRC channel on Freenode.
 | 
					You can find the sigrok developers in the #sigrok IRC channel on Libera.Chat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Website
 | 
					Website
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										269
									
								
								README.devices
								
								
								
								
							
							
						
						
									
										269
									
								
								README.devices
								
								
								
								
							| 
						 | 
					@ -14,6 +14,7 @@ the device is connected to the PC (usually via USB), before it can be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The default locations where libsigrok expects the firmware files are:
 | 
					The default locations where libsigrok expects the firmware files are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $SIGROK_FIRMWARE_DIR (environment variable)
 | 
				
			||||||
  $HOME/.local/share/sigrok-firmware
 | 
					  $HOME/.local/share/sigrok-firmware
 | 
				
			||||||
  $prefix/share/sigrok-firmware
 | 
					  $prefix/share/sigrok-firmware
 | 
				
			||||||
  /usr/local/share/sigrok-firmware
 | 
					  /usr/local/share/sigrok-firmware
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,11 @@ The following drivers/devices require a firmware upload upon connection:
 | 
				
			||||||
   'sigrok-firmware' repository/project under a license which allows us
 | 
					   'sigrok-firmware' repository/project under a license which allows us
 | 
				
			||||||
   to redistribute them.
 | 
					   to redistribute them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - dreamsourcelab-dslogic: The DreamSourceLab DSLogic/DSCope device series
 | 
				
			||||||
 | 
					   requires various firmware files and FPGA bitstream files.
 | 
				
			||||||
 | 
					   These can be extracted/downloaded from the vendor's GitHub repo using a
 | 
				
			||||||
 | 
					   tool from our 'sigrok-util' repository/project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - fx2lafw: Logic analyzers based on the Cypress FX2(LP) chip need the
 | 
					 - fx2lafw: Logic analyzers based on the Cypress FX2(LP) chip need the
 | 
				
			||||||
   firmware files from the 'sigrok-firmware-fx2lafw' repository/project.
 | 
					   firmware files from the 'sigrok-firmware-fx2lafw' repository/project.
 | 
				
			||||||
   The firmware is written from scratch and licensed under the GNU GPLv2+.
 | 
					   The firmware is written from scratch and licensed under the GNU GPLv2+.
 | 
				
			||||||
| 
						 | 
					@ -63,6 +69,11 @@ The following drivers/devices require a firmware upload upon connection:
 | 
				
			||||||
   These can be extracted from the vendor's Linux application using a tool
 | 
					   These can be extracted from the vendor's Linux application using a tool
 | 
				
			||||||
   from our 'sigrok-util' repository/project.
 | 
					   from our 'sigrok-util' repository/project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - saleae-logic-pro: The Saleae Logic Pro 16 needs a firmware file for the
 | 
				
			||||||
 | 
					   Cypress FX3 chip in the device, as well as an FPGA bitstream file.
 | 
				
			||||||
 | 
					   These can be extracted from the vendor's Linux application using a tool
 | 
				
			||||||
 | 
					   from our 'sigrok-util' repository/project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - sysclk-lwla:
 | 
					 - sysclk-lwla:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - The Sysclk LWLA1034 requires various bitstream files.
 | 
					    - The Sysclk LWLA1034 requires various bitstream files.
 | 
				
			||||||
| 
						 | 
					@ -73,6 +84,12 @@ The following drivers/devices require a firmware upload upon connection:
 | 
				
			||||||
      These can be extracted from the vendor's Windows drivers using a tool
 | 
					      These can be extracted from the vendor's Windows drivers using a tool
 | 
				
			||||||
      from our 'sigrok-util' repository/project.
 | 
					      from our 'sigrok-util' repository/project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - sysclk-sla5032: The Sysclk SLA5032 needs an FPGA bitstream file.
 | 
				
			||||||
 | 
					   This file can be copied (and renamed) from the Windows vendor software
 | 
				
			||||||
 | 
					   installation directory. Details:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     https://sigrok.org/wiki/Sysclk_SLA5032#Firmware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following drivers/devices do not need any firmware upload:
 | 
					The following drivers/devices do not need any firmware upload:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - agilent-dmm
 | 
					 - agilent-dmm
 | 
				
			||||||
| 
						 | 
					@ -81,54 +98,73 @@ The following drivers/devices do not need any firmware upload:
 | 
				
			||||||
 - atten-pps3xxx
 | 
					 - atten-pps3xxx
 | 
				
			||||||
 - baylibre-acme
 | 
					 - baylibre-acme
 | 
				
			||||||
 - beaglelogic
 | 
					 - beaglelogic
 | 
				
			||||||
 - brymen-bm86x
 | 
					 | 
				
			||||||
 - brymen-dmm
 | 
					 | 
				
			||||||
 - cem-dt-885x
 | 
					 - cem-dt-885x
 | 
				
			||||||
 - center-3xx (including all subdrivers)
 | 
					 - center-3xx (including all subdrivers)
 | 
				
			||||||
 - chronovu-la
 | 
					 - chronovu-la
 | 
				
			||||||
 - colead-slm
 | 
					 - colead-slm
 | 
				
			||||||
 - conrad-digi-35-cpu
 | 
					 - conrad-digi-35-cpu
 | 
				
			||||||
 - demo
 | 
					 - demo
 | 
				
			||||||
 | 
					 - fluke-45
 | 
				
			||||||
 - fluke-dmm
 | 
					 - fluke-dmm
 | 
				
			||||||
 - ftdi-la
 | 
					 - ftdi-la
 | 
				
			||||||
 - gmc-mh-1x-2x (including all subdrivers)
 | 
					 - gmc-mh-1x-2x (including all subdrivers)
 | 
				
			||||||
 - gwinstek-gds-800
 | 
					 - gwinstek-gds-800
 | 
				
			||||||
 | 
					 - gwinstek-gpd
 | 
				
			||||||
 - hameg-hmo
 | 
					 - hameg-hmo
 | 
				
			||||||
 | 
					 - hantek-4032l
 | 
				
			||||||
 - hp-3457a
 | 
					 - hp-3457a
 | 
				
			||||||
 | 
					 - hp-3478a
 | 
				
			||||||
 - hung-chang-dso-2100
 | 
					 - hung-chang-dso-2100
 | 
				
			||||||
 - ikalogic-scanalogic2
 | 
					 - ikalogic-scanalogic2
 | 
				
			||||||
 - ikalogic-scanaplus
 | 
					 - ikalogic-scanaplus
 | 
				
			||||||
 | 
					 - ipdbg-la
 | 
				
			||||||
 - kecheng-kc-330b
 | 
					 - kecheng-kc-330b
 | 
				
			||||||
 - kern-scale
 | 
					 - kern-scale
 | 
				
			||||||
 | 
					 - korad-kaxxxxp
 | 
				
			||||||
 - lascar-el-usb
 | 
					 - lascar-el-usb
 | 
				
			||||||
 | 
					 - lecroy-xstream
 | 
				
			||||||
 - link-mso19
 | 
					 - link-mso19
 | 
				
			||||||
 - manson-hcs-3xxx
 | 
					 - manson-hcs-3xxx
 | 
				
			||||||
 - maynuo-m97
 | 
					 - maynuo-m97
 | 
				
			||||||
 - mic-985xx (including all subdrivers)
 | 
					 - mic-985xx (including all subdrivers)
 | 
				
			||||||
 | 
					 - microchip-pickit2
 | 
				
			||||||
 | 
					 - mooshimeter-dmm
 | 
				
			||||||
 - motech-lps-30x
 | 
					 - motech-lps-30x
 | 
				
			||||||
 - norma-dmm
 | 
					 - norma-dmm
 | 
				
			||||||
 - openbench-logic-sniffer
 | 
					 - openbench-logic-sniffer
 | 
				
			||||||
 - pce-322a
 | 
					 - pce-322a
 | 
				
			||||||
 - pipistrello-ols
 | 
					 - pipistrello-ols
 | 
				
			||||||
 | 
					 - rdtech-dps
 | 
				
			||||||
 | 
					 - rigol-dg
 | 
				
			||||||
 - rigol-ds
 | 
					 - rigol-ds
 | 
				
			||||||
 | 
					 - rohde-schwarz-sme-0x
 | 
				
			||||||
 | 
					 - scpi-dmm
 | 
				
			||||||
 - scpi-pps
 | 
					 - scpi-pps
 | 
				
			||||||
 - serial-dmm (including all subdrivers)
 | 
					 - serial-dmm (including all subdrivers)
 | 
				
			||||||
 - serial-lcr (including all subdrivers)
 | 
					 - serial-lcr (including all subdrivers)
 | 
				
			||||||
 | 
					 - siglent-sds
 | 
				
			||||||
 - teleinfo
 | 
					 - teleinfo
 | 
				
			||||||
 - testo
 | 
					 - testo
 | 
				
			||||||
 - tondaj-sl-814
 | 
					 - tondaj-sl-814
 | 
				
			||||||
 - uni-t-dmm (including all subdrivers)
 | 
					 - uni-t-dmm (including all subdrivers)
 | 
				
			||||||
 - uni-t-ut32x
 | 
					 - uni-t-ut32x
 | 
				
			||||||
 - victor-dmm
 | 
					 | 
				
			||||||
 - yokogawa-dlm
 | 
					 - yokogawa-dlm
 | 
				
			||||||
 - zeroplus-logic-cube
 | 
					 - zeroplus-logic-cube
 | 
				
			||||||
 | 
					 - zketech-ebd-usb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Specifying serial ports
 | 
					Specifying serial ports
 | 
				
			||||||
-----------------------
 | 
					-----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Many devices supported by libsigrok use serial port based cables (real RS232
 | 
					Many devices supported by libsigrok use serial port based cables (real RS232
 | 
				
			||||||
or USB-to-serial ones) to connect to a PC.
 | 
					or USB-to-serial ones, CDC class) to connect to a PC. These serial cables are
 | 
				
			||||||
 | 
					supported by the libserialport library. Some vendors prefer to use HID chips
 | 
				
			||||||
 | 
					instead of CDC chips in their serial cables. These cables can get supported
 | 
				
			||||||
 | 
					by means of the hidapi library. Note that each chip type requires specific
 | 
				
			||||||
 | 
					support in the libsigrok library. Bluetooth connected devices may be supported
 | 
				
			||||||
 | 
					as well when they communicate by means of RFCOMM channels, or one of the
 | 
				
			||||||
 | 
					implemented BLE notification/indication approaches, and one of the Bluetooth
 | 
				
			||||||
 | 
					supporting platforms is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For all these devices, you need to specify the serial port they are connected
 | 
					For all these devices, you need to specify the serial port they are connected
 | 
				
			||||||
to (e.g. using the 'conn' option in sigrok-cli). It is not possible to scan
 | 
					to (e.g. using the 'conn' option in sigrok-cli). It is not possible to scan
 | 
				
			||||||
| 
						 | 
					@ -137,51 +173,43 @@ for such devices without specifying a serial port.
 | 
				
			||||||
Example:
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 $ sigrok-cli --driver <somedriver>:conn=/dev/ttyUSB0 ...
 | 
					 $ sigrok-cli --driver <somedriver>:conn=/dev/ttyUSB0 ...
 | 
				
			||||||
 | 
					 $ sigrok-cli --driver <somedriver>:conn=hid/cp2110 ...
 | 
				
			||||||
 | 
					 $ sigrok-cli --driver <somedriver>:conn=bt/rfcomm/01-23-45-67-89-ab ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following drivers/devices require a serial port specification:
 | 
					Formal syntax for serial communication:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - agilent-dmm
 | 
					 - COM ports (RS232, USB CDC):
 | 
				
			||||||
 - appa-55ii
 | 
					   conn=<com-port>
 | 
				
			||||||
 - atten-pps3xxx
 | 
					 - USB HID cables:
 | 
				
			||||||
 - brymen-dmm
 | 
					   conn=hid[/<chip>]
 | 
				
			||||||
 - cem-dt-885x
 | 
					   conn=hid[/<chip>]/usb=<bus>.<dev>[.<if>]
 | 
				
			||||||
 - center-3xx (including all subdrivers)
 | 
					   conn=hid[/<chip>]/raw=<path>
 | 
				
			||||||
 - colead-slm
 | 
					   conn=hid[/<chip>]/sn=<serno>
 | 
				
			||||||
 - conrad-digi-35-cpu
 | 
					   conn=hid[/<chip>]/iokit=<path>
 | 
				
			||||||
 - fluke-dmm
 | 
					   chip can be: bu86x, ch9325, cp2110, victor
 | 
				
			||||||
 - gmc-mh-1x-2x (including all subdrivers)
 | 
					   path may contain slashes
 | 
				
			||||||
 - hameg-hmo
 | 
					   path and serno are "greedy" (span to the end of the spec)
 | 
				
			||||||
 - link-mso19
 | 
					 - Bluetooth Classic and Bluetooth Low Energy (BLE):
 | 
				
			||||||
 - mic-985xx (including all subdrivers)
 | 
					   conn=bt/<conn>/<addr>
 | 
				
			||||||
 - norma-dmm
 | 
					   conn can be: rfcomm, ble122, nrf51, cc254x
 | 
				
			||||||
 - openbench-logic-sniffer
 | 
					   addr can be "dense" or separated, bt/cc254x/0123456789ab or
 | 
				
			||||||
 - rigol-ds (for RS232; not required for USBTMC or TCP)
 | 
					     bt/rfcomm/11-22-33-44-55-66 or bt/ble122/88:6b:12:34:56:78
 | 
				
			||||||
 - serial-dmm (including all subdrivers)
 | 
					     (note that colons may not be available when the conn= spec is taken
 | 
				
			||||||
 - serial-lcr (including all subdrivers)
 | 
					     from a string that separates fields by colon, e.g. in the "--driver
 | 
				
			||||||
 - teleinfo
 | 
					     <name>:conn=<spec>" example, that is why the dense form and the use
 | 
				
			||||||
 - tondaj-sl-814
 | 
					     of dashes for separation are supported)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following drivers/devices do not require a serial port specification:
 | 
					Some of the drivers implement a default for the connection. Some of the
 | 
				
			||||||
 | 
					drivers can auto-detect USB connected devices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - asix-sigma
 | 
					Beyond strict serial communication over COM ports (discussed above), the
 | 
				
			||||||
 - brymen-bm86x
 | 
					conn= property can also address specific USB devices, as well as specify TCP
 | 
				
			||||||
 - chronovu-la
 | 
					or VXI communication parameters. See these examples:
 | 
				
			||||||
 - demo
 | 
					
 | 
				
			||||||
 - fx2lafw
 | 
					 $ sigrok-cli --driver <somedriver>:conn=<vid>.<pid> ...
 | 
				
			||||||
 - hantek-dso
 | 
					 $ sigrok-cli --driver <somedriver>:conn=tcp-raw/<ipaddr>/<port> ...
 | 
				
			||||||
 - ikalogic-scanalogic2
 | 
					 $ sigrok-cli --driver <somedriver>:conn=vxi/<ipaddr> ...
 | 
				
			||||||
 - ikalogic-scanaplus
 | 
					 $ sigrok-cli --driver <somedriver>:conn=usbtmc/<bus>.<addr> ...
 | 
				
			||||||
 - kecheng-kc-330b
 | 
					 | 
				
			||||||
 - lascar-el-usb
 | 
					 | 
				
			||||||
 - pipistrello-ols
 | 
					 | 
				
			||||||
 - rigol-ds (USBTMC or TCP)
 | 
					 | 
				
			||||||
 - saleae-logic16
 | 
					 | 
				
			||||||
 - sysclk-lwla
 | 
					 | 
				
			||||||
 - uni-t-dmm (including all subdrivers)
 | 
					 | 
				
			||||||
 - uni-t-ut32x
 | 
					 | 
				
			||||||
 - victor-dmm
 | 
					 | 
				
			||||||
 - yokogawa-dlm (USBTMC or TCP)
 | 
					 | 
				
			||||||
 - zeroplus-logic-cube
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Specifying serial port parameters
 | 
					Specifying serial port parameters
 | 
				
			||||||
| 
						 | 
					@ -212,33 +240,53 @@ For USB-to-serial based devices, we recommended using our udev rules file
 | 
				
			||||||
(see below for details).
 | 
					(see below for details).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Permissions for USB devices (udev rules file)
 | 
					Permissions for USB devices (udev rules files)
 | 
				
			||||||
---------------------------------------------
 | 
					----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When using USB-based devices supported by libsigrok, the user running the
 | 
					When using USB-based devices supported by libsigrok, the user running the
 | 
				
			||||||
libsigrok frontend (e.g. sigrok-cli) has to have (read/write) permissions
 | 
					libsigrok frontend (e.g. sigrok-cli) has to have (read/write) permissions
 | 
				
			||||||
for the respective USB device.
 | 
					for the respective USB device.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
On Linux, this is accomplished using either 'chmod' (not recommended) or
 | 
					On Linux, this is accomplished using udev rules. libsigrok ships a rules
 | 
				
			||||||
using the udev rules file shipped with libsigrok (recommended).
 | 
					file containing all supported devices which can be detected reliably
 | 
				
			||||||
 | 
					(generic USB-to-serial converters are omitted, as these are used for a wide
 | 
				
			||||||
 | 
					range of devices, e.g. GPS receivers, which are not handled by libsigrok).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The file is available in contrib/z60_libsigrok.rules. It contains entries
 | 
					The file is available in contrib/60-libsigrok.rules. This file just contains
 | 
				
			||||||
for all libsigrok-supported (USB-based) devices and changes their group
 | 
					the list of devices and flags these devices with ID_SIGROK="1". Access is
 | 
				
			||||||
to 'plugdev' and the permissions to '664'.
 | 
					granted by the 61-libsigrok-plugdev.rules or 61-libsigrok-uaccess.rules files,
 | 
				
			||||||
 | 
					allowing access to members of the plugdev group or to currently logged in
 | 
				
			||||||
 | 
					users, respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
When using a libsigrok package from your favorite Linux distribution, the
 | 
					When using a libsigrok package from your favorite Linux distribution, the
 | 
				
			||||||
packager will have already taken care of properly installing the udev file
 | 
					files should already be installed in /usr/lib/udev/rules.d/, i.e.
 | 
				
			||||||
in the correct (distro-specific) place, and you don't have to do anything.
 | 
					60-libsigrok.rules and one of the access granting rules files. Use of
 | 
				
			||||||
The packager might also have adapted 'plugdev' and '664' as needed.
 | 
					61-libsigrok-uaccess.rules is encouraged on systemd distributions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The access policy can be locally overridden by placing appropriate rules in
 | 
				
			||||||
 | 
					/etc/udev/rules.d/, disabling or ammending the default policy. See the
 | 
				
			||||||
 | 
					udev documentation, e.g. man 7 udev, for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you're building from source, you need to copy the file to the place
 | 
					If you're building from source, you need to copy the file to the place
 | 
				
			||||||
where your distro expects such files. This is beyond the scope of this README,
 | 
					where udev will read these rules. Local rules should go to /etc/udev/rules.d.
 | 
				
			||||||
but generally the location could be e.g. /etc/udev/rules.d, or maybe
 | 
					Keep the file naming, otherwise interaction between the libsigrok rules and
 | 
				
			||||||
/lib/udev/rules.d, or something else. Afterwards you might have to restart
 | 
					rules shipped by the system will be broken.
 | 
				
			||||||
udev, e.g. via '/etc/init.d/udev restart' or similar, and you'll have to
 | 
					 | 
				
			||||||
re-attach your device via USB.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Please consult the udev docs of your distro for details.
 | 
					Please consult the udev docs for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Non-default drivers for commodity chips
 | 
				
			||||||
 | 
					---------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some vendors include common USB chips in their products yet assign device
 | 
				
			||||||
 | 
					specific VID:PID pairs. Which results in the necessity for extra steps
 | 
				
			||||||
 | 
					before the serial port can be used:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- GW Instek VCP, found in GDM-8000 and probably other meters: Install the
 | 
				
			||||||
 | 
					  vendors Windows driver to get access to a COM port. Or force the driver
 | 
				
			||||||
 | 
					  assignment on Linux:
 | 
				
			||||||
 | 
					    # modprobe cp210x
 | 
				
			||||||
 | 
					    # echo 2184 0030 > /sys/bus/usb-serial/drivers/cp210x/new_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cypress FX2 based devices
 | 
					Cypress FX2 based devices
 | 
				
			||||||
| 
						 | 
					@ -260,9 +308,11 @@ UNI-T DMM (and rebranded models) cables
 | 
				
			||||||
UNI-T multimeters (and rebranded devices, e.g. some Voltcraft models) can
 | 
					UNI-T multimeters (and rebranded devices, e.g. some Voltcraft models) can
 | 
				
			||||||
ship with different PC connectivity cables:
 | 
					ship with different PC connectivity cables:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - UT-D02 (RS232 cable)
 | 
				
			||||||
 - UT-D04 (USB/HID cable with Hoitek HE2325U chip, USB VID/PID 04fa:2490)
 | 
					 - UT-D04 (USB/HID cable with Hoitek HE2325U chip, USB VID/PID 04fa:2490)
 | 
				
			||||||
 - UT-D04 (USB/HID cable with WCH CH9325 chip, USB VID/PID 1a86:e008)
 | 
					 - UT-D04 (USB/HID cable with WCH CH9325 chip, USB VID/PID 1a86:e008)
 | 
				
			||||||
 - UT-D02 (RS232 cable)
 | 
					 - UT-D07 (Bluetooth adapter, ISSC BL79 BLETR chip)
 | 
				
			||||||
 | 
					 - UT-D09 (USB/HID cable with SiL CP2110 chip, USB VID/PID 10c4:ea80)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The above cables are all physically compatible (same IR connector shape)
 | 
					The above cables are all physically compatible (same IR connector shape)
 | 
				
			||||||
with all/most currently known UNI-T multimeters. For example, you can
 | 
					with all/most currently known UNI-T multimeters. For example, you can
 | 
				
			||||||
| 
						 | 
					@ -337,7 +387,12 @@ a short list for convenience:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - BBC Goertz Metrawatt M2110: Briefly press the "Start/Reset" button on the
 | 
					 - BBC Goertz Metrawatt M2110: Briefly press the "Start/Reset" button on the
 | 
				
			||||||
   interface panel on top.
 | 
					   interface panel on top.
 | 
				
			||||||
 | 
					 - Brymen BM257s: Press HOLD during power-on.
 | 
				
			||||||
 - Digitek DT4000ZC: Briefly press the "RS232" button.
 | 
					 - Digitek DT4000ZC: Briefly press the "RS232" button.
 | 
				
			||||||
 | 
					 - EEVBlog 121GW: Hold "1ms PEAK" until the "BT" indicator is shown.
 | 
				
			||||||
 | 
					 - ES51919 based LCR meters (DER EE DE-5000, PeakTech 2170, UNI-T UT612):
 | 
				
			||||||
 | 
					   Press the button with the "RS232" or "USB" or "PC link" label (usually
 | 
				
			||||||
 | 
					   the "up" cursor button).
 | 
				
			||||||
 - Gossen Metrawatt Metrahit 1x/2x devices, driver gmc-mh-1x-2x-rs232:
 | 
					 - Gossen Metrawatt Metrahit 1x/2x devices, driver gmc-mh-1x-2x-rs232:
 | 
				
			||||||
   - Power on the device with the "DATA" button pressed.
 | 
					   - Power on the device with the "DATA" button pressed.
 | 
				
			||||||
   - Metrahit 2x devices must be configured for the respective interface type.
 | 
					   - Metrahit 2x devices must be configured for the respective interface type.
 | 
				
			||||||
| 
						 | 
					@ -349,6 +404,14 @@ a short list for convenience:
 | 
				
			||||||
      'SI232 online' (28-29S) or 'SI232 store' (22-26x). The interface must
 | 
					      'SI232 online' (28-29S) or 'SI232 store' (22-26x). The interface must
 | 
				
			||||||
      be configured to the same baud rate as the host (default 9600).
 | 
					      be configured to the same baud rate as the host (default 9600).
 | 
				
			||||||
      Multimeter and interface must be configured to the same address.
 | 
					      Multimeter and interface must be configured to the same address.
 | 
				
			||||||
 | 
					 - GW Instek GDM-397: Press the "REL/RS232C (USB)" button for roughly 1 second.
 | 
				
			||||||
 | 
					 - GW Instek VCP: See the discussion on manual driver assignment to common
 | 
				
			||||||
 | 
					   USB to UART chips with non-default USB identification.
 | 
				
			||||||
 | 
					 - MASTECH MS6514: Press the "Setup/PC-Link" button for roughly 3 seconds.
 | 
				
			||||||
 | 
					 - Meterman 38XR: Press the "RS232" button.
 | 
				
			||||||
 | 
					 - Metrix MX56C: Press the PRINT button to have the meter send acquisition
 | 
				
			||||||
 | 
					   data via IR. Hold the PRINT button to adjust the meter's transmission
 | 
				
			||||||
 | 
					   interval.
 | 
				
			||||||
 - Norma DM950: If the interface doesn't work (e.g. USB-RS232 converter), power
 | 
					 - Norma DM950: If the interface doesn't work (e.g. USB-RS232 converter), power
 | 
				
			||||||
   on the device with "FUNC" pressed (to power the interface from the DMM).
 | 
					   on the device with "FUNC" pressed (to power the interface from the DMM).
 | 
				
			||||||
 - PCE PCE-DM32: Briefly press the "RS232" button.
 | 
					 - PCE PCE-DM32: Briefly press the "RS232" button.
 | 
				
			||||||
| 
						 | 
					@ -359,6 +422,7 @@ a short list for convenience:
 | 
				
			||||||
 - UNI-T UT61B/C/D: Press the "REL/RS232/USB" button for roughly 1 second.
 | 
					 - UNI-T UT61B/C/D: Press the "REL/RS232/USB" button for roughly 1 second.
 | 
				
			||||||
 - UNI-T UT71x: Press the "SEND/-/MAXMIN" button for roughly 1 second.
 | 
					 - UNI-T UT71x: Press the "SEND/-/MAXMIN" button for roughly 1 second.
 | 
				
			||||||
   Briefly pressing the "EXIT" button leaves this mode again.
 | 
					   Briefly pressing the "EXIT" button leaves this mode again.
 | 
				
			||||||
 | 
					 - UNI-T UT181A: In the "SETUP" menu set "Communication" to "ON".
 | 
				
			||||||
 - UNI-T UT325: Briefly press the "SEND" button (as per manual). However, it
 | 
					 - UNI-T UT325: Briefly press the "SEND" button (as per manual). However, it
 | 
				
			||||||
   appears that in practice you don't have to press the button (at least on
 | 
					   appears that in practice you don't have to press the button (at least on
 | 
				
			||||||
   some versions of the device), simply connect the device via USB.
 | 
					   some versions of the device), simply connect the device via USB.
 | 
				
			||||||
| 
						 | 
					@ -407,3 +471,84 @@ Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 $ sigrok-cli --driver ols:conn=/dev/ttyACM0 ...
 | 
					 $ sigrok-cli --driver ols:conn=/dev/ttyACM0 ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					JTAGulator
 | 
				
			||||||
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Grand Idea Studio JTAGulator also implements the SUMP protocol and
 | 
				
			||||||
 | 
					thus is covered by the OLS driver. See the vendor's wiki on details how
 | 
				
			||||||
 | 
					to enable the Logic Analyzer mode of operation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  https://github.com/grandideastudio/jtagulator/wiki/Logic-Analyzer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mooshimeter
 | 
				
			||||||
 | 
					-----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Mooshim Engineering Mooshimeter is controlled via Bluetooth Low Energy
 | 
				
			||||||
 | 
					(sometimes called Bluetooth 4.0), as such it requires a supported Bluetooth
 | 
				
			||||||
 | 
					interface available. The 'conn' option is required and must contain the
 | 
				
			||||||
 | 
					Bluetooth MAC address of the meter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $ sigrok-cli --driver mooshimeter-dmm:conn=12-34-56-78-9A-BC ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the Mooshimeter has no physical interface on the meter itself, the
 | 
				
			||||||
 | 
					channel configuration is set with the 'channel_config' option. The format
 | 
				
			||||||
 | 
					of this option is 'CH1,CH2' where each channel configuration has the form
 | 
				
			||||||
 | 
					'MODE:RANGE:ANALYSIS', with later parts being optional. In addition for
 | 
				
			||||||
 | 
					CLI compatibility, the ',' in the channels can also be a '/' and the ':' in
 | 
				
			||||||
 | 
					the individual configuration can be a ';'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available channel 1 modes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - Current, A: Current in amps
 | 
				
			||||||
 | 
					  - Temperature, T, K: Internal meter temperature in Kelvin
 | 
				
			||||||
 | 
					  - Resistance, Ohm, W: Resistance in ohms
 | 
				
			||||||
 | 
					  - Diode, D: Diode voltage
 | 
				
			||||||
 | 
					  - Aux, LV: Auxiliary (W input) low voltage sensor (1.2V max)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Available channel 2 modes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - Voltage, V: Voltage
 | 
				
			||||||
 | 
					  - Temperature, T, K: Internal meter temperature in Kelvin
 | 
				
			||||||
 | 
					  - Resistance, Ohm, W: Resistance in ohms
 | 
				
			||||||
 | 
					  - Diode, D: Diode voltage
 | 
				
			||||||
 | 
					  - Aux, LV: Auxiliary (W input) low voltage sensor (1.2V max)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Only one channel can use the shared inputs at a time (e.g. if CH1 is measuring
 | 
				
			||||||
 | 
					resistance, CH2 cannot measure low voltage). Temperature is excepted from
 | 
				
			||||||
 | 
					this, so the meter can measure internal temperature and low voltage at the
 | 
				
			||||||
 | 
					same time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Additionally, the meter can calculate the real power of both channels. This
 | 
				
			||||||
 | 
					generally only makes sense when CH1 is set to current and CH2 is set to a
 | 
				
			||||||
 | 
					voltage and so it is disabled by default. It must be enabled by enabling the
 | 
				
			||||||
 | 
					'P' channel (the third channel).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The range of the channel specification sets the maximum input for that channel
 | 
				
			||||||
 | 
					and is rounded up to the next value the meter itself supports. For example,
 | 
				
			||||||
 | 
					specifying 50 for the voltage will result in the actual maximum of 60.
 | 
				
			||||||
 | 
					Specifying 61 would result in 600. If omitted, sigrok will perform
 | 
				
			||||||
 | 
					auto-ranging of the channel by selecting the next greater value than the
 | 
				
			||||||
 | 
					latest maximum.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The analysis option sets how the meter reports its internal sampling buffer
 | 
				
			||||||
 | 
					to sigrok:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - Mean, DC: The default is a simple arithmetic mean of the sample buffer
 | 
				
			||||||
 | 
					 - RMS, AC: The root mean square of the sample buffer
 | 
				
			||||||
 | 
					 - Buf, Buffer, Samples: Report the entire sample buffer to sigrok. This
 | 
				
			||||||
 | 
					   results in packets that contain all the samples in the buffer instead
 | 
				
			||||||
 | 
					   of a single output value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The size of the sample buffer is set with the 'avg_samples' option, while
 | 
				
			||||||
 | 
					the sampling rate is set with the 'samplerate' option. So the update rate
 | 
				
			||||||
 | 
					is avg_samples/samplerate. Both are rounded up to the next supported value
 | 
				
			||||||
 | 
					by the meter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $ sigrok-cli -c channel_config="Aux;0.1/T" --driver mooshimeter-dmm...
 | 
				
			||||||
 | 
					  $ sigrok-cli -c channel_config="A;;AC/V;;AC" --driver mooshimeter-dmm...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DataType *ConfigKey::data_type() const
 | 
					const DataType *ConfigKey::data_type() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
						const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
				
			||||||
| 
						 | 
					@ -6,7 +8,7 @@ const DataType *ConfigKey::data_type() const
 | 
				
			||||||
	return DataType::get(info->datatype);
 | 
						return DataType::get(info->datatype);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string ConfigKey::identifier() const
 | 
					std::string ConfigKey::identifier() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
						const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
				
			||||||
	if (!info)
 | 
						if (!info)
 | 
				
			||||||
| 
						 | 
					@ -14,7 +16,7 @@ string ConfigKey::identifier() const
 | 
				
			||||||
	return valid_string(info->id);
 | 
						return valid_string(info->id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string ConfigKey::description() const
 | 
					std::string ConfigKey::description() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
						const struct sr_key_info *info = sr_key_info_get(SR_KEY_CONFIG, id());
 | 
				
			||||||
	if (!info)
 | 
						if (!info)
 | 
				
			||||||
| 
						 | 
					@ -22,7 +24,7 @@ string ConfigKey::description() const
 | 
				
			||||||
	return valid_string(info->name);
 | 
						return valid_string(info->name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ConfigKey *ConfigKey::get_by_identifier(string identifier)
 | 
					const ConfigKey *ConfigKey::get_by_identifier(std::string identifier)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct sr_key_info *info = sr_key_info_name_get(SR_KEY_CONFIG, identifier.c_str());
 | 
						const struct sr_key_info *info = sr_key_info_name_get(SR_KEY_CONFIG, identifier.c_str());
 | 
				
			||||||
	if (!info)
 | 
						if (!info)
 | 
				
			||||||
| 
						 | 
					@ -30,8 +32,6 @@ const ConfigKey *ConfigKey::get_by_identifier(string identifier)
 | 
				
			||||||
	return get(info->key);
 | 
						return get(info->key);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef HAVE_STOI_STOD
 | 
					#ifndef HAVE_STOI_STOD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Fallback implementation of stoi and stod */
 | 
					/* Fallback implementation of stoi and stod */
 | 
				
			||||||
| 
						 | 
					@ -70,12 +70,12 @@ static inline double stod( const std::string& str )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Glib::VariantBase ConfigKey::parse_string(string value) const
 | 
					Glib::VariantBase ConfigKey::parse_string(std::string value, enum sr_datatype dt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GVariant *variant;
 | 
						GVariant *variant;
 | 
				
			||||||
	uint64_t p, q;
 | 
						uint64_t p, q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (data_type()->id())
 | 
						switch (dt)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case SR_T_UINT64:
 | 
							case SR_T_UINT64:
 | 
				
			||||||
			check(sr_parse_sizestring(value.c_str(), &p));
 | 
								check(sr_parse_sizestring(value.c_str(), &p));
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ Glib::VariantBase ConfigKey::parse_string(string value) const
 | 
				
			||||||
		case SR_T_FLOAT:
 | 
							case SR_T_FLOAT:
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				variant = g_variant_new_double(stod(value));
 | 
									variant = g_variant_new_double(stod(value));
 | 
				
			||||||
			} catch (invalid_argument) {
 | 
								} catch (invalid_argument&) {
 | 
				
			||||||
				throw Error(SR_ERR_ARG);
 | 
									throw Error(SR_ERR_ARG);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ Glib::VariantBase ConfigKey::parse_string(string value) const
 | 
				
			||||||
		case SR_T_INT32:
 | 
							case SR_T_INT32:
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				variant = g_variant_new_int32(stoi(value));
 | 
									variant = g_variant_new_int32(stoi(value));
 | 
				
			||||||
			} catch (invalid_argument) {
 | 
								} catch (invalid_argument&) {
 | 
				
			||||||
				throw Error(SR_ERR_ARG);
 | 
									throw Error(SR_ERR_ARG);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -116,3 +116,8 @@ Glib::VariantBase ConfigKey::parse_string(string value) const
 | 
				
			||||||
	return Glib::VariantBase(variant, false);
 | 
						return Glib::VariantBase(variant, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Glib::VariantBase ConfigKey::parse_string(std::string value) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum sr_datatype dt = (enum sr_datatype)(data_type()->id());
 | 
				
			||||||
 | 
						return parse_string(value, dt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,11 @@
 | 
				
			||||||
    /** Data type used for this configuration key. */
 | 
					    /** Data type used for this configuration key. */
 | 
				
			||||||
    const DataType *data_type() const;
 | 
					    const DataType *data_type() const;
 | 
				
			||||||
    /** String identifier for this configuration key, suitable for CLI use. */
 | 
					    /** String identifier for this configuration key, suitable for CLI use. */
 | 
				
			||||||
    string identifier() const;
 | 
					    std::string identifier() const;
 | 
				
			||||||
    /** Description of this configuration key. */
 | 
					    /** Description of this configuration key. */
 | 
				
			||||||
    string description() const;
 | 
					    std::string description() const;
 | 
				
			||||||
    /** Get configuration key by string identifier. */
 | 
					    /** Get configuration key by string identifier. */
 | 
				
			||||||
    static const ConfigKey *get_by_identifier(string identifier);
 | 
					    static const ConfigKey *get_by_identifier(std::string identifier);
 | 
				
			||||||
    /** Parse a string argument into the appropriate type for this key. */
 | 
					    /** Parse a string argument into the appropriate type for this key. */
 | 
				
			||||||
    Glib::VariantBase parse_string(string value) const;
 | 
					    static Glib::VariantBase parse_string(std::string value, enum sr_datatype dt);
 | 
				
			||||||
 | 
					    Glib::VariantBase parse_string(std::string value) const;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
vector<const QuantityFlag *>
 | 
					std::vector<const QuantityFlag *>
 | 
				
			||||||
    QuantityFlag::flags_from_mask(unsigned int mask)
 | 
					    QuantityFlag::flags_from_mask(unsigned int mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto result = vector<const QuantityFlag *>();
 | 
					    auto result = std::vector<const QuantityFlag *>();
 | 
				
			||||||
    while (mask)
 | 
					    while (mask)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        unsigned int new_mask = mask & (mask - 1);
 | 
					        unsigned int new_mask = mask & (mask - 1);
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ vector<const QuantityFlag *>
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int QuantityFlag::mask_from_flags(vector<const QuantityFlag *> flags)
 | 
					unsigned int QuantityFlag::mask_from_flags(std::vector<const QuantityFlag *> flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    unsigned int result = 0;
 | 
					    unsigned int result = 0;
 | 
				
			||||||
    for (auto flag : flags)
 | 
					    for (auto flag : flags)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
	/** Get flags corresponding to a bitmask. */
 | 
						/** Get flags corresponding to a bitmask. */
 | 
				
			||||||
	static vector<const QuantityFlag *>
 | 
						static std::vector<const QuantityFlag *>
 | 
				
			||||||
		flags_from_mask(unsigned int mask);
 | 
							flags_from_mask(unsigned int mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/** Get bitmask corresponding to a set of flags. */
 | 
						/** Get bitmask corresponding to a set of flags. */
 | 
				
			||||||
	static unsigned int mask_from_flags(
 | 
						static unsigned int mask_from_flags(
 | 
				
			||||||
		vector<const QuantityFlag *> flags);
 | 
							std::vector<const QuantityFlag *> flags);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,8 +18,9 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Needed for isascii(), as used in the GNU libstdc++ headers */
 | 
					/* Needed for isascii(), as used in the GNU libstdc++ headers */
 | 
				
			||||||
 | 
					/* Needed in strutil.c for POSIX.1-2008 locale functions */
 | 
				
			||||||
#ifndef _XOPEN_SOURCE
 | 
					#ifndef _XOPEN_SOURCE
 | 
				
			||||||
#define _XOPEN_SOURCE 600
 | 
					#define _XOPEN_SOURCE 700
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,8 @@
 | 
				
			||||||
namespace sigrok
 | 
					namespace sigrok
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Helper function to translate C errors to C++ exceptions. */
 | 
					/** Helper function to translate C errors to C++ exceptions. */
 | 
				
			||||||
static void check(int result)
 | 
					static void check(int result)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -128,19 +131,19 @@ Context::Context() :
 | 
				
			||||||
	if (struct sr_dev_driver **driver_list = sr_driver_list(_structure))
 | 
						if (struct sr_dev_driver **driver_list = sr_driver_list(_structure))
 | 
				
			||||||
		for (int i = 0; driver_list[i]; i++) {
 | 
							for (int i = 0; driver_list[i]; i++) {
 | 
				
			||||||
			unique_ptr<Driver> driver {new Driver{driver_list[i]}};
 | 
								unique_ptr<Driver> driver {new Driver{driver_list[i]}};
 | 
				
			||||||
			_drivers.insert(make_pair(driver->name(), move(driver)));
 | 
								_drivers.emplace(driver->name(), move(driver));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (const struct sr_input_module **input_list = sr_input_list())
 | 
						if (const struct sr_input_module **input_list = sr_input_list())
 | 
				
			||||||
		for (int i = 0; input_list[i]; i++) {
 | 
							for (int i = 0; input_list[i]; i++) {
 | 
				
			||||||
			unique_ptr<InputFormat> input {new InputFormat{input_list[i]}};
 | 
								unique_ptr<InputFormat> input {new InputFormat{input_list[i]}};
 | 
				
			||||||
			_input_formats.insert(make_pair(input->name(), move(input)));
 | 
								_input_formats.emplace(input->name(), move(input));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (const struct sr_output_module **output_list = sr_output_list())
 | 
						if (const struct sr_output_module **output_list = sr_output_list())
 | 
				
			||||||
		for (int i = 0; output_list[i]; i++) {
 | 
							for (int i = 0; output_list[i]; i++) {
 | 
				
			||||||
			unique_ptr<OutputFormat> output {new OutputFormat{output_list[i]}};
 | 
								unique_ptr<OutputFormat> output {new OutputFormat{output_list[i]}};
 | 
				
			||||||
			_output_formats.insert(make_pair(output->name(), move(output)));
 | 
								_output_formats.emplace(output->name(), move(output));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,11 +160,10 @@ string Context::lib_version()
 | 
				
			||||||
map<string, shared_ptr<Driver>> Context::drivers()
 | 
					map<string, shared_ptr<Driver>> Context::drivers()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<Driver>> result;
 | 
						map<string, shared_ptr<Driver>> result;
 | 
				
			||||||
	for (const auto &entry: _drivers)
 | 
						for (const auto &entry: _drivers) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &name = entry.first;
 | 
							const auto &name = entry.first;
 | 
				
			||||||
		const auto &driver = entry.second;
 | 
							const auto &driver = entry.second;
 | 
				
			||||||
		result.insert({name, driver->share_owned_by(shared_from_this())});
 | 
							result.emplace(name, driver->share_owned_by(shared_from_this()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -169,23 +171,47 @@ map<string, shared_ptr<Driver>> Context::drivers()
 | 
				
			||||||
map<string, shared_ptr<InputFormat>> Context::input_formats()
 | 
					map<string, shared_ptr<InputFormat>> Context::input_formats()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<InputFormat>> result;
 | 
						map<string, shared_ptr<InputFormat>> result;
 | 
				
			||||||
	for (const auto &entry: _input_formats)
 | 
						for (const auto &entry: _input_formats) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &name = entry.first;
 | 
							const auto &name = entry.first;
 | 
				
			||||||
		const auto &input_format = entry.second;
 | 
							const auto &input_format = entry.second;
 | 
				
			||||||
		result.insert({name, input_format->share_owned_by(shared_from_this())});
 | 
							result.emplace(name, input_format->share_owned_by(shared_from_this()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<InputFormat> Context::input_format_match(string filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct sr_input *input;
 | 
				
			||||||
 | 
						const struct sr_input_module *imod;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Have the input module looked up for the specified file.
 | 
				
			||||||
 | 
						 * Failed lookup (or "successful lookup" with an empty result)
 | 
				
			||||||
 | 
						 * are non-fatal. Free the sr_input that was created by the
 | 
				
			||||||
 | 
						 * lookup routine, but grab the input module kind and return an
 | 
				
			||||||
 | 
						 * InputFormat instance to the application. This works because
 | 
				
			||||||
 | 
						 * the application passes a filename, no input data got buffered
 | 
				
			||||||
 | 
						 * in the sr_input that we release.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						input = NULL;
 | 
				
			||||||
 | 
						rc = sr_input_scan_file(filename.c_str(), &input);
 | 
				
			||||||
 | 
						if (rc != SR_OK)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						if (!input)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
						imod = sr_input_module_get(input);
 | 
				
			||||||
 | 
						sr_input_free(input);
 | 
				
			||||||
 | 
						return shared_ptr<InputFormat>{new InputFormat{imod}, default_delete<InputFormat>{}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
map<string, shared_ptr<OutputFormat>> Context::output_formats()
 | 
					map<string, shared_ptr<OutputFormat>> Context::output_formats()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<OutputFormat>> result;
 | 
						map<string, shared_ptr<OutputFormat>> result;
 | 
				
			||||||
	for (const auto &entry: _output_formats)
 | 
						for (const auto &entry: _output_formats) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &name = entry.first;
 | 
							const auto &name = entry.first;
 | 
				
			||||||
		const auto &output_format = entry.second;
 | 
							const auto &output_format = entry.second;
 | 
				
			||||||
		result.insert({name, output_format->share_owned_by(shared_from_this())});
 | 
							result.emplace(name, output_format->share_owned_by(shared_from_this()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -213,12 +239,9 @@ static int call_log_callback(void *cb_data, int loglevel,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto *const callback = static_cast<LogCallbackFunction *>(cb_data);
 | 
						auto *const callback = static_cast<LogCallbackFunction *>(cb_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	try
 | 
						try {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		(*callback)(LogLevel::get(loglevel), message.get());
 | 
							(*callback)(LogLevel::get(loglevel), message.get());
 | 
				
			||||||
	}
 | 
						} catch (Error &e) {
 | 
				
			||||||
	catch (Error e)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return e.result;
 | 
							return e.result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,8 +304,7 @@ shared_ptr<Packet> Context::create_meta_packet(
 | 
				
			||||||
	map<const ConfigKey *, Glib::VariantBase> config)
 | 
						map<const ConfigKey *, Glib::VariantBase> config)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto meta = g_new0(struct sr_datafeed_meta, 1);
 | 
						auto meta = g_new0(struct sr_datafeed_meta, 1);
 | 
				
			||||||
	for (const auto &input : config)
 | 
						for (const auto &input : config) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &key = input.first;
 | 
							const auto &key = input.first;
 | 
				
			||||||
		const auto &value = input.second;
 | 
							const auto &value = input.second;
 | 
				
			||||||
		auto *const output = g_new(struct sr_config, 1);
 | 
							auto *const output = g_new(struct sr_config, 1);
 | 
				
			||||||
| 
						 | 
					@ -312,7 +334,7 @@ shared_ptr<Packet> Context::create_logic_packet(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shared_ptr<Packet> Context::create_analog_packet(
 | 
					shared_ptr<Packet> Context::create_analog_packet(
 | 
				
			||||||
	vector<shared_ptr<Channel> > channels,
 | 
						vector<shared_ptr<Channel> > channels,
 | 
				
			||||||
	float *data_pointer, unsigned int num_samples, const Quantity *mq,
 | 
						const float *data_pointer, unsigned int num_samples, const Quantity *mq,
 | 
				
			||||||
	const Unit *unit, vector<const QuantityFlag *> mqflags)
 | 
						const Unit *unit, vector<const QuantityFlag *> mqflags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	auto analog = g_new0(struct sr_datafeed_analog, 1);
 | 
						auto analog = g_new0(struct sr_datafeed_analog, 1);
 | 
				
			||||||
| 
						 | 
					@ -350,13 +372,21 @@ shared_ptr<Packet> Context::create_analog_packet(
 | 
				
			||||||
	spec->spec_digits = 0;
 | 
						spec->spec_digits = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	analog->num_samples = num_samples;
 | 
						analog->num_samples = num_samples;
 | 
				
			||||||
	analog->data = data_pointer;
 | 
						analog->data = (float*)data_pointer;
 | 
				
			||||||
	auto packet = g_new(struct sr_datafeed_packet, 1);
 | 
						auto packet = g_new(struct sr_datafeed_packet, 1);
 | 
				
			||||||
	packet->type = SR_DF_ANALOG;
 | 
						packet->type = SR_DF_ANALOG;
 | 
				
			||||||
	packet->payload = analog;
 | 
						packet->payload = analog;
 | 
				
			||||||
	return shared_ptr<Packet>{new Packet{nullptr, packet}, default_delete<Packet>{}};
 | 
						return shared_ptr<Packet>{new Packet{nullptr, packet}, default_delete<Packet>{}};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<Packet> Context::create_end_packet()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto packet = g_new(struct sr_datafeed_packet, 1);
 | 
				
			||||||
 | 
						packet->type = SR_DF_END;
 | 
				
			||||||
 | 
						return shared_ptr<Packet>{new Packet{nullptr, packet},
 | 
				
			||||||
 | 
							default_delete<Packet>{}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shared_ptr<Session> Context::load_session(string filename)
 | 
					shared_ptr<Session> Context::load_session(string filename)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return shared_ptr<Session>{
 | 
						return shared_ptr<Session>{
 | 
				
			||||||
| 
						 | 
					@ -446,16 +476,14 @@ vector<shared_ptr<HardwareDevice>> Driver::scan(
 | 
				
			||||||
	map<const ConfigKey *, Glib::VariantBase> options)
 | 
						map<const ConfigKey *, Glib::VariantBase> options)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Initialise the driver if not yet done. */
 | 
						/* Initialise the driver if not yet done. */
 | 
				
			||||||
	if (!_initialized)
 | 
						if (!_initialized) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		check(sr_driver_init(_parent->_structure, _structure));
 | 
							check(sr_driver_init(_parent->_structure, _structure));
 | 
				
			||||||
		_initialized = true;
 | 
							_initialized = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Translate scan options to GSList of struct sr_config pointers. */
 | 
						/* Translate scan options to GSList of struct sr_config pointers. */
 | 
				
			||||||
	GSList *option_list = nullptr;
 | 
						GSList *option_list = nullptr;
 | 
				
			||||||
	for (const auto &entry : options)
 | 
						for (const auto &entry : options) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &key = entry.first;
 | 
							const auto &key = entry.first;
 | 
				
			||||||
		const auto &value = entry.second;
 | 
							const auto &value = entry.second;
 | 
				
			||||||
		auto *const config = g_new(struct sr_config, 1);
 | 
							auto *const config = g_new(struct sr_config, 1);
 | 
				
			||||||
| 
						 | 
					@ -473,8 +501,7 @@ vector<shared_ptr<HardwareDevice>> Driver::scan(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create device objects. */
 | 
						/* Create device objects. */
 | 
				
			||||||
	vector<shared_ptr<HardwareDevice>> result;
 | 
						vector<shared_ptr<HardwareDevice>> result;
 | 
				
			||||||
	for (GSList *device = device_list; device; device = device->next)
 | 
						for (GSList *device = device_list; device; device = device->next) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto *const sdi = static_cast<struct sr_dev_inst *>(device->data);
 | 
							auto *const sdi = static_cast<struct sr_dev_inst *>(device->data);
 | 
				
			||||||
		shared_ptr<HardwareDevice> hwdev {
 | 
							shared_ptr<HardwareDevice> hwdev {
 | 
				
			||||||
			new HardwareDevice{shared_from_this(), sdi},
 | 
								new HardwareDevice{shared_from_this(), sdi},
 | 
				
			||||||
| 
						 | 
					@ -570,23 +597,22 @@ Device::Device(struct sr_dev_inst *structure) :
 | 
				
			||||||
	Configurable(sr_dev_inst_driver_get(structure), structure, nullptr),
 | 
						Configurable(sr_dev_inst_driver_get(structure), structure, nullptr),
 | 
				
			||||||
	_structure(structure)
 | 
						_structure(structure)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	for (GSList *entry = sr_dev_inst_channels_get(structure); entry; entry = entry->next)
 | 
						for (GSList *entry = sr_dev_inst_channels_get(structure); entry; entry = entry->next) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto *const ch = static_cast<struct sr_channel *>(entry->data);
 | 
							auto *const ch = static_cast<struct sr_channel *>(entry->data);
 | 
				
			||||||
		unique_ptr<Channel> channel {new Channel{ch}};
 | 
							unique_ptr<Channel> channel {new Channel{ch}};
 | 
				
			||||||
		_channels.insert(make_pair(ch, move(channel)));
 | 
							_channels.emplace(ch, move(channel));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (GSList *entry = sr_dev_inst_channel_groups_get(structure); entry; entry = entry->next)
 | 
						for (GSList *entry = sr_dev_inst_channel_groups_get(structure); entry; entry = entry->next) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto *const cg = static_cast<struct sr_channel_group *>(entry->data);
 | 
							auto *const cg = static_cast<struct sr_channel_group *>(entry->data);
 | 
				
			||||||
		unique_ptr<ChannelGroup> group {new ChannelGroup{this, cg}};
 | 
							unique_ptr<ChannelGroup> group {new ChannelGroup{this, cg}};
 | 
				
			||||||
		_channel_groups.insert(make_pair(group->name(), move(group)));
 | 
							_channel_groups.emplace(group->name(), move(group));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Device::~Device()
 | 
					Device::~Device()
 | 
				
			||||||
{}
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string Device::vendor() const
 | 
					string Device::vendor() const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -632,11 +658,10 @@ map<string, shared_ptr<ChannelGroup>>
 | 
				
			||||||
Device::channel_groups()
 | 
					Device::channel_groups()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<ChannelGroup>> result;
 | 
						map<string, shared_ptr<ChannelGroup>> result;
 | 
				
			||||||
	for (const auto &entry: _channel_groups)
 | 
						for (const auto &entry: _channel_groups) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		const auto &name = entry.first;
 | 
							const auto &name = entry.first;
 | 
				
			||||||
		const auto &channel_group = entry.second;
 | 
							const auto &channel_group = entry.second;
 | 
				
			||||||
		result.insert({name, channel_group->share_owned_by(get_shared_from_this())});
 | 
							result.emplace(name, channel_group->share_owned_by(get_shared_from_this()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -695,7 +720,7 @@ shared_ptr<Channel> UserDevice::add_channel(unsigned int index,
 | 
				
			||||||
	GSList *const last = g_slist_last(sr_dev_inst_channels_get(Device::_structure));
 | 
						GSList *const last = g_slist_last(sr_dev_inst_channels_get(Device::_structure));
 | 
				
			||||||
	auto *const ch = static_cast<struct sr_channel *>(last->data);
 | 
						auto *const ch = static_cast<struct sr_channel *>(last->data);
 | 
				
			||||||
	unique_ptr<Channel> channel {new Channel{ch}};
 | 
						unique_ptr<Channel> channel {new Channel{ch}};
 | 
				
			||||||
	_channels.insert(make_pair(ch, move(channel)));
 | 
						_channels.emplace(ch, move(channel));
 | 
				
			||||||
	return get_channel(ch);
 | 
						return get_channel(ch);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -918,9 +943,10 @@ Session::Session(shared_ptr<Context> context, string filename) :
 | 
				
			||||||
	for (GSList *dev = dev_list; dev; dev = dev->next) {
 | 
						for (GSList *dev = dev_list; dev; dev = dev->next) {
 | 
				
			||||||
		auto *const sdi = static_cast<struct sr_dev_inst *>(dev->data);
 | 
							auto *const sdi = static_cast<struct sr_dev_inst *>(dev->data);
 | 
				
			||||||
		unique_ptr<SessionDevice> device {new SessionDevice{sdi}};
 | 
							unique_ptr<SessionDevice> device {new SessionDevice{sdi}};
 | 
				
			||||||
		_owned_devices.insert(make_pair(sdi, move(device)));
 | 
							_owned_devices.emplace(sdi, move(device));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_context->_session = this;
 | 
						_context->_session = this;
 | 
				
			||||||
 | 
						g_slist_free(dev_list);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Session::~Session()
 | 
					Session::~Session()
 | 
				
			||||||
| 
						 | 
					@ -955,6 +981,7 @@ vector<shared_ptr<Device>> Session::devices()
 | 
				
			||||||
		auto *const sdi = static_cast<struct sr_dev_inst *>(dev->data);
 | 
							auto *const sdi = static_cast<struct sr_dev_inst *>(dev->data);
 | 
				
			||||||
		result.push_back(get_device(sdi));
 | 
							result.push_back(get_device(sdi));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						g_slist_free(dev_list);
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1299,6 +1326,48 @@ vector<const QuantityFlag *> Analog::mq_flags() const
 | 
				
			||||||
	return QuantityFlag::flags_from_mask(_structure->meaning->mqflags);
 | 
						return QuantityFlag::flags_from_mask(_structure->meaning->mqflags);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<Logic> Analog::get_logic_via_threshold(float threshold,
 | 
				
			||||||
 | 
						uint8_t *data_ptr) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto datafeed = g_new(struct sr_datafeed_logic, 1);
 | 
				
			||||||
 | 
						datafeed->length = num_samples();
 | 
				
			||||||
 | 
						datafeed->unitsize = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data_ptr)
 | 
				
			||||||
 | 
							datafeed->data = data_ptr;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							datafeed->data = g_malloc(datafeed->length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shared_ptr<Logic> logic =
 | 
				
			||||||
 | 
							shared_ptr<Logic>{new Logic{datafeed}, default_delete<Logic>{}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						check(sr_a2l_threshold(_structure, threshold,
 | 
				
			||||||
 | 
							(uint8_t*)datafeed->data, datafeed->length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return logic;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<Logic> Analog::get_logic_via_schmitt_trigger(float lo_thr,
 | 
				
			||||||
 | 
						float hi_thr, uint8_t *state, uint8_t *data_ptr) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto datafeed = g_new(struct sr_datafeed_logic, 1);
 | 
				
			||||||
 | 
						datafeed->length = num_samples();
 | 
				
			||||||
 | 
						datafeed->unitsize = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data_ptr)
 | 
				
			||||||
 | 
							datafeed->data = data_ptr;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							datafeed->data = g_malloc(datafeed->length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shared_ptr<Logic> logic =
 | 
				
			||||||
 | 
							shared_ptr<Logic>{new Logic{datafeed}, default_delete<Logic>{}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						check(sr_a2l_schmitt_trigger(_structure, lo_thr, hi_thr, state,
 | 
				
			||||||
 | 
							(uint8_t*)datafeed->data, datafeed->length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return logic;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Rational::Rational(const struct sr_rational *structure) :
 | 
					Rational::Rational(const struct sr_rational *structure) :
 | 
				
			||||||
	_structure(structure)
 | 
						_structure(structure)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1361,15 +1430,14 @@ map<string, shared_ptr<Option>> InputFormat::options()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<Option>> result;
 | 
						map<string, shared_ptr<Option>> result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (const struct sr_option **options = sr_input_options_get(_structure))
 | 
						if (const struct sr_option **options = sr_input_options_get(_structure)) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		shared_ptr<const struct sr_option *> option_array
 | 
							shared_ptr<const struct sr_option *> option_array
 | 
				
			||||||
			{options, &sr_input_options_free};
 | 
								{options, &sr_input_options_free};
 | 
				
			||||||
		for (int i = 0; options[i]; i++) {
 | 
							for (int i = 0; options[i]; i++) {
 | 
				
			||||||
			shared_ptr<Option> opt {
 | 
								shared_ptr<Option> opt {
 | 
				
			||||||
				new Option{options[i], option_array},
 | 
									new Option{options[i], option_array},
 | 
				
			||||||
				default_delete<Option>{}};
 | 
									default_delete<Option>{}};
 | 
				
			||||||
			result.insert({opt->id(), move(opt)});
 | 
								result.emplace(opt->id(), move(opt));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
| 
						 | 
					@ -1392,8 +1460,7 @@ Input::Input(shared_ptr<Context> context, const struct sr_input *structure) :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
shared_ptr<InputDevice> Input::device()
 | 
					shared_ptr<InputDevice> Input::device()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!_device)
 | 
						if (!_device) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto sdi = sr_input_dev_inst_get(_structure);
 | 
							auto sdi = sr_input_dev_inst_get(_structure);
 | 
				
			||||||
		if (!sdi)
 | 
							if (!sdi)
 | 
				
			||||||
			throw Error(SR_ERR_NA);
 | 
								throw Error(SR_ERR_NA);
 | 
				
			||||||
| 
						 | 
					@ -1483,6 +1550,28 @@ vector<Glib::VariantBase> Option::values() const
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Glib::VariantBase Option::parse_string(string value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						enum sr_datatype dt;
 | 
				
			||||||
 | 
						Glib::VariantBase dflt = default_value();
 | 
				
			||||||
 | 
						GVariant *tmpl = dflt.gobj();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_UINT64)) {
 | 
				
			||||||
 | 
							dt = SR_T_UINT64;
 | 
				
			||||||
 | 
						} else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_STRING)) {
 | 
				
			||||||
 | 
							dt = SR_T_STRING;
 | 
				
			||||||
 | 
						} else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_BOOLEAN)) {
 | 
				
			||||||
 | 
							dt = SR_T_BOOL;
 | 
				
			||||||
 | 
						} else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_DOUBLE)) {
 | 
				
			||||||
 | 
							dt = SR_T_FLOAT;
 | 
				
			||||||
 | 
						} else if (g_variant_is_of_type(tmpl, G_VARIANT_TYPE_INT32)) {
 | 
				
			||||||
 | 
							dt = SR_T_INT32;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							throw Error(SR_ERR_BUG);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ConfigKey::parse_string(value, dt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OutputFormat::OutputFormat(const struct sr_output_module *structure) :
 | 
					OutputFormat::OutputFormat(const struct sr_output_module *structure) :
 | 
				
			||||||
	_structure(structure)
 | 
						_structure(structure)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1515,15 +1604,14 @@ map<string, shared_ptr<Option>> OutputFormat::options()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	map<string, shared_ptr<Option>> result;
 | 
						map<string, shared_ptr<Option>> result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (const struct sr_option **options = sr_output_options_get(_structure))
 | 
						if (const struct sr_option **options = sr_output_options_get(_structure)) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		shared_ptr<const struct sr_option *> option_array
 | 
							shared_ptr<const struct sr_option *> option_array
 | 
				
			||||||
			{options, &sr_output_options_free};
 | 
								{options, &sr_output_options_free};
 | 
				
			||||||
		for (int i = 0; options[i]; i++) {
 | 
							for (int i = 0; options[i]; i++) {
 | 
				
			||||||
			shared_ptr<Option> opt {
 | 
								shared_ptr<Option> opt {
 | 
				
			||||||
				new Option{options[i], option_array},
 | 
									new Option{options[i], option_array},
 | 
				
			||||||
				default_delete<Option>{}};
 | 
									default_delete<Option>{}};
 | 
				
			||||||
			result.insert({opt->id(), move(opt)});
 | 
								result.emplace(opt->id(), move(opt));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
| 
						 | 
					@ -1575,18 +1663,20 @@ Output::~Output()
 | 
				
			||||||
	check(sr_output_free(_structure));
 | 
						check(sr_output_free(_structure));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shared_ptr<OutputFormat> Output::format()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return _format;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
string Output::receive(shared_ptr<Packet> packet)
 | 
					string Output::receive(shared_ptr<Packet> packet)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GString *out;
 | 
						GString *out;
 | 
				
			||||||
	check(sr_output_send(_structure, packet->_structure, &out));
 | 
						check(sr_output_send(_structure, packet->_structure, &out));
 | 
				
			||||||
	if (out)
 | 
						if (out) {
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		auto result = string(out->str, out->str + out->len);
 | 
							auto result = string(out->str, out->str + out->len);
 | 
				
			||||||
		g_string_free(out, true);
 | 
							g_string_free(out, true);
 | 
				
			||||||
		return result;
 | 
							return result;
 | 
				
			||||||
	}
 | 
						} else {
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return string();
 | 
							return string();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,6 +78,7 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | 
				
			||||||
#include <glibmm.h>
 | 
					#include <glibmm.h>
 | 
				
			||||||
G_GNUC_END_IGNORE_DEPRECATIONS
 | 
					G_GNUC_END_IGNORE_DEPRECATIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
#include <stdexcept>
 | 
					#include <stdexcept>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
| 
						 | 
					@ -87,8 +88,6 @@ G_GNUC_END_IGNORE_DEPRECATIONS
 | 
				
			||||||
namespace sigrok
 | 
					namespace sigrok
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace std;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Forward declarations */
 | 
					/* Forward declarations */
 | 
				
			||||||
class SR_API Error;
 | 
					class SR_API Error;
 | 
				
			||||||
class SR_API Context;
 | 
					class SR_API Context;
 | 
				
			||||||
| 
						 | 
					@ -124,7 +123,7 @@ class SR_API Option;
 | 
				
			||||||
class SR_API UserDevice;
 | 
					class SR_API UserDevice;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Exception thrown when an error code is returned by any libsigrok call. */
 | 
					/** Exception thrown when an error code is returned by any libsigrok call. */
 | 
				
			||||||
class SR_API Error: public exception
 | 
					class SR_API Error: public std::exception
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	explicit Error(int result);
 | 
						explicit Error(int result);
 | 
				
			||||||
| 
						 | 
					@ -139,7 +138,7 @@ class SR_API ParentOwned
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	/* Weak pointer for shared_from_this() implementation. */
 | 
						/* Weak pointer for shared_from_this() implementation. */
 | 
				
			||||||
	weak_ptr<Class> _weak_this;
 | 
						std::weak_ptr<Class> _weak_this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static void reset_parent(Class *object)
 | 
						static void reset_parent(Class *object)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -162,14 +161,14 @@ protected:
 | 
				
			||||||
		This strategy ensures that the destructors for both the child and
 | 
							This strategy ensures that the destructors for both the child and
 | 
				
			||||||
		the parent are called at the correct time, i.e. only when all
 | 
							the parent are called at the correct time, i.e. only when all
 | 
				
			||||||
		references to both the parent and all its children are gone. */
 | 
							references to both the parent and all its children are gone. */
 | 
				
			||||||
	shared_ptr<Parent> _parent;
 | 
						std::shared_ptr<Parent> _parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ParentOwned() {}
 | 
						ParentOwned() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Note, this implementation will create a new smart_ptr if none exists. */
 | 
						/* Note, this implementation will create a new smart_ptr if none exists. */
 | 
				
			||||||
	shared_ptr<Class> shared_from_this()
 | 
						std::shared_ptr<Class> shared_from_this()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		shared_ptr<Class> shared = _weak_this.lock();
 | 
							std::shared_ptr<Class> shared = _weak_this.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!shared)
 | 
							if (!shared)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -180,7 +179,7 @@ protected:
 | 
				
			||||||
		return shared;
 | 
							return shared;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shared_ptr<Class> share_owned_by(shared_ptr<Parent> parent)
 | 
						std::shared_ptr<Class> share_owned_by(std::shared_ptr<Parent> parent)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!parent)
 | 
							if (!parent)
 | 
				
			||||||
			throw Error(SR_ERR_BUG);
 | 
								throw Error(SR_ERR_BUG);
 | 
				
			||||||
| 
						 | 
					@ -190,7 +189,7 @@ protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/* Get parent object that owns this object. */
 | 
						/* Get parent object that owns this object. */
 | 
				
			||||||
	shared_ptr<Parent> parent()
 | 
						std::shared_ptr<Parent> parent()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return _parent;
 | 
							return _parent;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -198,14 +197,14 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Base template for classes whose resources are owned by the user. */
 | 
					/* Base template for classes whose resources are owned by the user. */
 | 
				
			||||||
template <class Class>
 | 
					template <class Class>
 | 
				
			||||||
class SR_API UserOwned : public enable_shared_from_this<Class>
 | 
					class SR_API UserOwned : public std::enable_shared_from_this<Class>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
	UserOwned() {}
 | 
						UserOwned() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	shared_ptr<Class> shared_from_this()
 | 
						std::shared_ptr<Class> shared_from_this()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto shared = enable_shared_from_this<Class>::shared_from_this();
 | 
							auto shared = std::enable_shared_from_this<Class>::shared_from_this();
 | 
				
			||||||
		if (!shared)
 | 
							if (!shared)
 | 
				
			||||||
			throw Error(SR_ERR_BUG);
 | 
								throw Error(SR_ERR_BUG);
 | 
				
			||||||
		return shared;
 | 
							return shared;
 | 
				
			||||||
| 
						 | 
					@ -213,7 +212,7 @@ protected:
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Type of log callback */
 | 
					/** Type of log callback */
 | 
				
			||||||
typedef function<void(const LogLevel *, string message)> LogCallbackFunction;
 | 
					typedef std::function<void(const LogLevel *, std::string message)> LogCallbackFunction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Resource reader delegate. */
 | 
					/** Resource reader delegate. */
 | 
				
			||||||
class SR_API ResourceReader
 | 
					class SR_API ResourceReader
 | 
				
			||||||
| 
						 | 
					@ -223,7 +222,7 @@ public:
 | 
				
			||||||
	virtual ~ResourceReader();
 | 
						virtual ~ResourceReader();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	/** Resource open hook. */
 | 
						/** Resource open hook. */
 | 
				
			||||||
	virtual void open(struct sr_resource *res, string name) = 0;
 | 
						virtual void open(struct sr_resource *res, std::string name) = 0;
 | 
				
			||||||
	/** Resource close hook. */
 | 
						/** Resource close hook. */
 | 
				
			||||||
	virtual void close(struct sr_resource *res) = 0;
 | 
						virtual void close(struct sr_resource *res) = 0;
 | 
				
			||||||
	/** Resource read hook. */
 | 
						/** Resource read hook. */
 | 
				
			||||||
| 
						 | 
					@ -243,17 +242,19 @@ class SR_API Context : public UserOwned<Context>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Create new context */
 | 
						/** Create new context */
 | 
				
			||||||
	static shared_ptr<Context> create();
 | 
						static std::shared_ptr<Context> create();
 | 
				
			||||||
	/** libsigrok package version. */
 | 
						/** libsigrok package version. */
 | 
				
			||||||
	static string package_version();
 | 
						static std::string package_version();
 | 
				
			||||||
	/** libsigrok library version. */
 | 
						/** libsigrok library version. */
 | 
				
			||||||
	static string lib_version();
 | 
						static std::string lib_version();
 | 
				
			||||||
	/** Available hardware drivers, indexed by name. */
 | 
						/** Available hardware drivers, indexed by name. */
 | 
				
			||||||
	map<string, shared_ptr<Driver> > drivers();
 | 
						std::map<std::string, std::shared_ptr<Driver> > drivers();
 | 
				
			||||||
	/** Available input formats, indexed by name. */
 | 
						/** Available input formats, indexed by name. */
 | 
				
			||||||
	map<string, shared_ptr<InputFormat> > input_formats();
 | 
						std::map<std::string, std::shared_ptr<InputFormat> > input_formats();
 | 
				
			||||||
 | 
						/** Lookup the responsible input module for an input file. */
 | 
				
			||||||
 | 
						std::shared_ptr<InputFormat> input_format_match(std::string filename);
 | 
				
			||||||
	/** Available output formats, indexed by name. */
 | 
						/** Available output formats, indexed by name. */
 | 
				
			||||||
	map<string, shared_ptr<OutputFormat> > output_formats();
 | 
						std::map<std::string, std::shared_ptr<OutputFormat> > output_formats();
 | 
				
			||||||
	/** Current log level. */
 | 
						/** Current log level. */
 | 
				
			||||||
	const LogLevel *log_level() const;
 | 
						const LogLevel *log_level() const;
 | 
				
			||||||
	/** Set the log level.
 | 
						/** Set the log level.
 | 
				
			||||||
| 
						 | 
					@ -268,41 +269,43 @@ public:
 | 
				
			||||||
	 * @param reader The resource reader delegate, or nullptr to unset. */
 | 
						 * @param reader The resource reader delegate, or nullptr to unset. */
 | 
				
			||||||
	void set_resource_reader(ResourceReader *reader);
 | 
						void set_resource_reader(ResourceReader *reader);
 | 
				
			||||||
	/** Create a new session. */
 | 
						/** Create a new session. */
 | 
				
			||||||
	shared_ptr<Session> create_session();
 | 
						std::shared_ptr<Session> create_session();
 | 
				
			||||||
	/** Create a new user device. */
 | 
						/** Create a new user device. */
 | 
				
			||||||
	shared_ptr<UserDevice> create_user_device(
 | 
						std::shared_ptr<UserDevice> create_user_device(
 | 
				
			||||||
		string vendor, string model, string version);
 | 
							std::string vendor, std::string model, std::string version);
 | 
				
			||||||
	/** Create a header packet. */
 | 
						/** Create a header packet. */
 | 
				
			||||||
	shared_ptr<Packet> create_header_packet(Glib::TimeVal start_time);
 | 
						std::shared_ptr<Packet> create_header_packet(Glib::TimeVal start_time);
 | 
				
			||||||
	/** Create a meta packet. */
 | 
						/** Create a meta packet. */
 | 
				
			||||||
	shared_ptr<Packet> create_meta_packet(
 | 
						std::shared_ptr<Packet> create_meta_packet(
 | 
				
			||||||
		map<const ConfigKey *, Glib::VariantBase> config);
 | 
							std::map<const ConfigKey *, Glib::VariantBase> config);
 | 
				
			||||||
	/** Create a logic packet. */
 | 
						/** Create a logic packet. */
 | 
				
			||||||
	shared_ptr<Packet> create_logic_packet(
 | 
						std::shared_ptr<Packet> create_logic_packet(
 | 
				
			||||||
		void *data_pointer, size_t data_length, unsigned int unit_size);
 | 
							void *data_pointer, size_t data_length, unsigned int unit_size);
 | 
				
			||||||
	/** Create an analog packet. */
 | 
						/** Create an analog packet. */
 | 
				
			||||||
	shared_ptr<Packet> create_analog_packet(
 | 
						std::shared_ptr<Packet> create_analog_packet(
 | 
				
			||||||
		vector<shared_ptr<Channel> > channels,
 | 
							std::vector<std::shared_ptr<Channel> > channels,
 | 
				
			||||||
		float *data_pointer, unsigned int num_samples, const Quantity *mq,
 | 
							const float *data_pointer, unsigned int num_samples, const Quantity *mq,
 | 
				
			||||||
		const Unit *unit, vector<const QuantityFlag *> mqflags);
 | 
							const Unit *unit, std::vector<const QuantityFlag *> mqflags);
 | 
				
			||||||
 | 
						/** Create an end packet. */
 | 
				
			||||||
 | 
						std::shared_ptr<Packet> create_end_packet();
 | 
				
			||||||
	/** Load a saved session.
 | 
						/** Load a saved session.
 | 
				
			||||||
	 * @param filename File name string. */
 | 
						 * @param filename File name string. */
 | 
				
			||||||
	shared_ptr<Session> load_session(string filename);
 | 
						std::shared_ptr<Session> load_session(std::string filename);
 | 
				
			||||||
	/** Create a new trigger.
 | 
						/** Create a new trigger.
 | 
				
			||||||
	 * @param name Name string for new trigger. */
 | 
						 * @param name Name string for new trigger. */
 | 
				
			||||||
	shared_ptr<Trigger> create_trigger(string name);
 | 
						std::shared_ptr<Trigger> create_trigger(std::string name);
 | 
				
			||||||
	/** Open an input file.
 | 
						/** Open an input file.
 | 
				
			||||||
	 * @param filename File name string. */
 | 
						 * @param filename File name string. */
 | 
				
			||||||
	shared_ptr<Input> open_file(string filename);
 | 
						std::shared_ptr<Input> open_file(std::string filename);
 | 
				
			||||||
	/** Open an input stream based on header data.
 | 
						/** Open an input stream based on header data.
 | 
				
			||||||
	 * @param header Initial data from stream. */
 | 
						 * @param header Initial data from stream. */
 | 
				
			||||||
	shared_ptr<Input> open_stream(string header);
 | 
						std::shared_ptr<Input> open_stream(std::string header);
 | 
				
			||||||
	map<string, string> serials(shared_ptr<Driver> driver) const;
 | 
						std::map<std::string, std::string> serials(std::shared_ptr<Driver> driver) const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	struct sr_context *_structure;
 | 
						struct sr_context *_structure;
 | 
				
			||||||
	map<string, unique_ptr<Driver> > _drivers;
 | 
						std::map<std::string, std::unique_ptr<Driver> > _drivers;
 | 
				
			||||||
	map<string, unique_ptr<InputFormat> > _input_formats;
 | 
						std::map<std::string, std::unique_ptr<InputFormat> > _input_formats;
 | 
				
			||||||
	map<string, unique_ptr<OutputFormat> > _output_formats;
 | 
						std::map<std::string, std::unique_ptr<OutputFormat> > _output_formats;
 | 
				
			||||||
	Session *_session;
 | 
						Session *_session;
 | 
				
			||||||
	LogCallbackFunction _log_callback;
 | 
						LogCallbackFunction _log_callback;
 | 
				
			||||||
	Context();
 | 
						Context();
 | 
				
			||||||
| 
						 | 
					@ -317,7 +320,7 @@ class SR_API Configurable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Supported configuration keys. */
 | 
						/** Supported configuration keys. */
 | 
				
			||||||
	set<const ConfigKey *> config_keys() const;
 | 
						std::set<const ConfigKey *> config_keys() const;
 | 
				
			||||||
	/** Read configuration for the given key.
 | 
						/** Read configuration for the given key.
 | 
				
			||||||
	 * @param key ConfigKey to read. */
 | 
						 * @param key ConfigKey to read. */
 | 
				
			||||||
	Glib::VariantBase config_get(const ConfigKey *key) const;
 | 
						Glib::VariantBase config_get(const ConfigKey *key) const;
 | 
				
			||||||
| 
						 | 
					@ -330,7 +333,7 @@ public:
 | 
				
			||||||
	Glib::VariantContainerBase config_list(const ConfigKey *key) const;
 | 
						Glib::VariantContainerBase config_list(const ConfigKey *key) const;
 | 
				
			||||||
	/** Enumerate configuration capabilities for the given configuration key.
 | 
						/** Enumerate configuration capabilities for the given configuration key.
 | 
				
			||||||
	 * @param key ConfigKey to enumerate capabilities for. */
 | 
						 * @param key ConfigKey to enumerate capabilities for. */
 | 
				
			||||||
	set<const Capability *> config_capabilities(const ConfigKey *key) const;
 | 
						std::set<const Capability *> config_capabilities(const ConfigKey *key) const;
 | 
				
			||||||
	/** Check whether a configuration capability is supported for a given key.
 | 
						/** Check whether a configuration capability is supported for a given key.
 | 
				
			||||||
	 * @param key ConfigKey to check.
 | 
						 * @param key ConfigKey to check.
 | 
				
			||||||
	 * @param capability Capability to check for. */
 | 
						 * @param capability Capability to check for. */
 | 
				
			||||||
| 
						 | 
					@ -351,19 +354,19 @@ class SR_API Driver : public ParentOwned<Driver, Context>, public Configurable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Name of this driver. */
 | 
						/** Name of this driver. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** Long name for this driver. */
 | 
						/** Long name for this driver. */
 | 
				
			||||||
	string long_name() const;
 | 
						std::string long_name() const;
 | 
				
			||||||
	/** Scan options supported by this driver. */
 | 
						/** Scan options supported by this driver. */
 | 
				
			||||||
	set<const ConfigKey *> scan_options() const;
 | 
						std::set<const ConfigKey *> scan_options() const;
 | 
				
			||||||
	/** Scan for devices and return a list of devices found.
 | 
						/** Scan for devices and return a list of devices found.
 | 
				
			||||||
	 * @param options Mapping of (ConfigKey, value) pairs. */
 | 
						 * @param options Mapping of (ConfigKey, value) pairs. */
 | 
				
			||||||
	vector<shared_ptr<HardwareDevice> > scan(map<const ConfigKey *, Glib::VariantBase>
 | 
						std::vector<std::shared_ptr<HardwareDevice> > scan(std::map<const ConfigKey *, Glib::VariantBase>
 | 
				
			||||||
			options = map<const ConfigKey *, Glib::VariantBase>());
 | 
								options = std::map<const ConfigKey *, Glib::VariantBase>());
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	struct sr_dev_driver *_structure;
 | 
						struct sr_dev_driver *_structure;
 | 
				
			||||||
	bool _initialized;
 | 
						bool _initialized;
 | 
				
			||||||
	vector<HardwareDevice *> _devices;
 | 
						std::vector<HardwareDevice *> _devices;
 | 
				
			||||||
	explicit Driver(struct sr_dev_driver *structure);
 | 
						explicit Driver(struct sr_dev_driver *structure);
 | 
				
			||||||
	~Driver();
 | 
						~Driver();
 | 
				
			||||||
	friend class Context;
 | 
						friend class Context;
 | 
				
			||||||
| 
						 | 
					@ -377,19 +380,19 @@ class SR_API Device : public Configurable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Vendor name for this device. */
 | 
						/** Vendor name for this device. */
 | 
				
			||||||
	string vendor() const;
 | 
						std::string vendor() const;
 | 
				
			||||||
	/** Model name for this device. */
 | 
						/** Model name for this device. */
 | 
				
			||||||
	string model() const;
 | 
						std::string model() const;
 | 
				
			||||||
	/** Version string for this device. */
 | 
						/** Version string for this device. */
 | 
				
			||||||
	string version() const;
 | 
						std::string version() const;
 | 
				
			||||||
	/** Serial number for this device. */
 | 
						/** Serial number for this device. */
 | 
				
			||||||
	string serial_number() const;
 | 
						std::string serial_number() const;
 | 
				
			||||||
	/** Connection ID for this device. */
 | 
						/** Connection ID for this device. */
 | 
				
			||||||
	string connection_id() const;
 | 
						std::string connection_id() const;
 | 
				
			||||||
	/** List of the channels available on this device. */
 | 
						/** List of the channels available on this device. */
 | 
				
			||||||
	vector<shared_ptr<Channel> > channels();
 | 
						std::vector<std::shared_ptr<Channel> > channels();
 | 
				
			||||||
	/** Channel groups available on this device, indexed by name. */
 | 
						/** Channel groups available on this device, indexed by name. */
 | 
				
			||||||
	map<string, shared_ptr<ChannelGroup> > channel_groups();
 | 
						std::map<std::string, std::shared_ptr<ChannelGroup> > channel_groups();
 | 
				
			||||||
	/** Open device. */
 | 
						/** Open device. */
 | 
				
			||||||
	void open();
 | 
						void open();
 | 
				
			||||||
	/** Close device. */
 | 
						/** Close device. */
 | 
				
			||||||
| 
						 | 
					@ -397,13 +400,13 @@ public:
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
	explicit Device(struct sr_dev_inst *structure);
 | 
						explicit Device(struct sr_dev_inst *structure);
 | 
				
			||||||
	~Device();
 | 
						~Device();
 | 
				
			||||||
	virtual shared_ptr<Device> get_shared_from_this() = 0;
 | 
						virtual std::shared_ptr<Device> get_shared_from_this() = 0;
 | 
				
			||||||
	shared_ptr<Channel> get_channel(struct sr_channel *ptr);
 | 
						std::shared_ptr<Channel> get_channel(struct sr_channel *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sr_dev_inst *_structure;
 | 
						struct sr_dev_inst *_structure;
 | 
				
			||||||
	map<struct sr_channel *, unique_ptr<Channel> > _channels;
 | 
						std::map<struct sr_channel *, std::unique_ptr<Channel> > _channels;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	map<string, unique_ptr<ChannelGroup> > _channel_groups;
 | 
						std::map<std::string, std::unique_ptr<ChannelGroup> > _channel_groups;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Session;
 | 
						friend class Session;
 | 
				
			||||||
	friend class Channel;
 | 
						friend class Channel;
 | 
				
			||||||
| 
						 | 
					@ -420,12 +423,12 @@ class SR_API HardwareDevice :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Driver providing this device. */
 | 
						/** Driver providing this device. */
 | 
				
			||||||
	shared_ptr<Driver> driver();
 | 
						std::shared_ptr<Driver> driver();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	HardwareDevice(shared_ptr<Driver> driver, struct sr_dev_inst *structure);
 | 
						HardwareDevice(std::shared_ptr<Driver> driver, struct sr_dev_inst *structure);
 | 
				
			||||||
	~HardwareDevice();
 | 
						~HardwareDevice();
 | 
				
			||||||
	shared_ptr<Device> get_shared_from_this();
 | 
						std::shared_ptr<Device> get_shared_from_this();
 | 
				
			||||||
	shared_ptr<Driver> _driver;
 | 
						std::shared_ptr<Driver> _driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Driver;
 | 
						friend class Driver;
 | 
				
			||||||
	friend class ChannelGroup;
 | 
						friend class ChannelGroup;
 | 
				
			||||||
| 
						 | 
					@ -439,11 +442,11 @@ class SR_API UserDevice :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Add a new channel to this device. */
 | 
						/** Add a new channel to this device. */
 | 
				
			||||||
	shared_ptr<Channel> add_channel(unsigned int index, const ChannelType *type, string name);
 | 
						std::shared_ptr<Channel> add_channel(unsigned int index, const ChannelType *type, std::string name);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	UserDevice(string vendor, string model, string version);
 | 
						UserDevice(std::string vendor, std::string model, std::string version);
 | 
				
			||||||
	~UserDevice();
 | 
						~UserDevice();
 | 
				
			||||||
	shared_ptr<Device> get_shared_from_this();
 | 
						std::shared_ptr<Device> get_shared_from_this();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Context;
 | 
						friend class Context;
 | 
				
			||||||
	friend struct std::default_delete<UserDevice>;
 | 
						friend struct std::default_delete<UserDevice>;
 | 
				
			||||||
| 
						 | 
					@ -455,10 +458,10 @@ class SR_API Channel :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Current name of this channel. */
 | 
						/** Current name of this channel. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** Set the name of this channel. *
 | 
						/** Set the name of this channel. *
 | 
				
			||||||
	 * @param name Name string to set. */
 | 
						 * @param name Name string to set. */
 | 
				
			||||||
	void set_name(string name);
 | 
						void set_name(std::string name);
 | 
				
			||||||
	/** Type of this channel. */
 | 
						/** Type of this channel. */
 | 
				
			||||||
	const ChannelType *type() const;
 | 
						const ChannelType *type() const;
 | 
				
			||||||
	/** Enabled status of this channel. */
 | 
						/** Enabled status of this channel. */
 | 
				
			||||||
| 
						 | 
					@ -489,13 +492,13 @@ class SR_API ChannelGroup :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Name of this channel group. */
 | 
						/** Name of this channel group. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** List of the channels in this group. */
 | 
						/** List of the channels in this group. */
 | 
				
			||||||
	vector<shared_ptr<Channel> > channels();
 | 
						std::vector<std::shared_ptr<Channel> > channels();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	ChannelGroup(const Device *device, struct sr_channel_group *structure);
 | 
						ChannelGroup(const Device *device, struct sr_channel_group *structure);
 | 
				
			||||||
	~ChannelGroup();
 | 
						~ChannelGroup();
 | 
				
			||||||
	vector<Channel *> _channels;
 | 
						std::vector<Channel *> _channels;
 | 
				
			||||||
	friend class Device;
 | 
						friend class Device;
 | 
				
			||||||
	friend struct std::default_delete<ChannelGroup>;
 | 
						friend struct std::default_delete<ChannelGroup>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -505,17 +508,17 @@ class SR_API Trigger : public UserOwned<Trigger>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Name of this trigger configuration. */
 | 
						/** Name of this trigger configuration. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** List of the stages in this trigger. */
 | 
						/** List of the stages in this trigger. */
 | 
				
			||||||
	vector<shared_ptr<TriggerStage> > stages();
 | 
						std::vector<std::shared_ptr<TriggerStage> > stages();
 | 
				
			||||||
	/** Add a new stage to this trigger. */
 | 
						/** Add a new stage to this trigger. */
 | 
				
			||||||
	shared_ptr<TriggerStage> add_stage();
 | 
						std::shared_ptr<TriggerStage> add_stage();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	Trigger(shared_ptr<Context> context, string name);
 | 
						Trigger(std::shared_ptr<Context> context, std::string name);
 | 
				
			||||||
	~Trigger();
 | 
						~Trigger();
 | 
				
			||||||
	struct sr_trigger *_structure;
 | 
						struct sr_trigger *_structure;
 | 
				
			||||||
	shared_ptr<Context> _context;
 | 
						std::shared_ptr<Context> _context;
 | 
				
			||||||
	vector<unique_ptr<TriggerStage> > _stages;
 | 
						std::vector<std::unique_ptr<TriggerStage> > _stages;
 | 
				
			||||||
	friend class Context;
 | 
						friend class Context;
 | 
				
			||||||
	friend class Session;
 | 
						friend class Session;
 | 
				
			||||||
	friend struct std::default_delete<Trigger>;
 | 
						friend struct std::default_delete<Trigger>;
 | 
				
			||||||
| 
						 | 
					@ -529,19 +532,19 @@ public:
 | 
				
			||||||
	/** Index number of this stage. */
 | 
						/** Index number of this stage. */
 | 
				
			||||||
	int number() const;
 | 
						int number() const;
 | 
				
			||||||
	/** List of match conditions on this stage. */
 | 
						/** List of match conditions on this stage. */
 | 
				
			||||||
	vector<shared_ptr<TriggerMatch> > matches();
 | 
						std::vector<std::shared_ptr<TriggerMatch> > matches();
 | 
				
			||||||
	/** Add a new match condition to this stage.
 | 
						/** Add a new match condition to this stage.
 | 
				
			||||||
	 * @param channel Channel to match on.
 | 
						 * @param channel Channel to match on.
 | 
				
			||||||
	 * @param type TriggerMatchType to apply. */
 | 
						 * @param type TriggerMatchType to apply. */
 | 
				
			||||||
	void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type);
 | 
						void add_match(std::shared_ptr<Channel> channel, const TriggerMatchType *type);
 | 
				
			||||||
	/** Add a new match condition to this stage.
 | 
						/** Add a new match condition to this stage.
 | 
				
			||||||
	 * @param channel Channel to match on.
 | 
						 * @param channel Channel to match on.
 | 
				
			||||||
	 * @param type TriggerMatchType to apply.
 | 
						 * @param type TriggerMatchType to apply.
 | 
				
			||||||
	 * @param value Threshold value. */
 | 
						 * @param value Threshold value. */
 | 
				
			||||||
	void add_match(shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
 | 
						void add_match(std::shared_ptr<Channel> channel, const TriggerMatchType *type, float value);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	struct sr_trigger_stage *_structure;
 | 
						struct sr_trigger_stage *_structure;
 | 
				
			||||||
	vector<unique_ptr<TriggerMatch> > _matches;
 | 
						std::vector<std::unique_ptr<TriggerMatch> > _matches;
 | 
				
			||||||
	explicit TriggerStage(struct sr_trigger_stage *structure);
 | 
						explicit TriggerStage(struct sr_trigger_stage *structure);
 | 
				
			||||||
	~TriggerStage();
 | 
						~TriggerStage();
 | 
				
			||||||
	friend class Trigger;
 | 
						friend class Trigger;
 | 
				
			||||||
| 
						 | 
					@ -554,25 +557,25 @@ class SR_API TriggerMatch :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Channel this condition matches on. */
 | 
						/** Channel this condition matches on. */
 | 
				
			||||||
	shared_ptr<Channel> channel();
 | 
						std::shared_ptr<Channel> channel();
 | 
				
			||||||
	/** Type of match. */
 | 
						/** Type of match. */
 | 
				
			||||||
	const TriggerMatchType *type() const;
 | 
						const TriggerMatchType *type() const;
 | 
				
			||||||
	/** Threshold value. */
 | 
						/** Threshold value. */
 | 
				
			||||||
	float value() const;
 | 
						float value() const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	TriggerMatch(struct sr_trigger_match *structure, shared_ptr<Channel> channel);
 | 
						TriggerMatch(struct sr_trigger_match *structure, std::shared_ptr<Channel> channel);
 | 
				
			||||||
	~TriggerMatch();
 | 
						~TriggerMatch();
 | 
				
			||||||
	struct sr_trigger_match *_structure;
 | 
						struct sr_trigger_match *_structure;
 | 
				
			||||||
	shared_ptr<Channel> _channel;
 | 
						std::shared_ptr<Channel> _channel;
 | 
				
			||||||
	friend class TriggerStage;
 | 
						friend class TriggerStage;
 | 
				
			||||||
	friend struct std::default_delete<TriggerMatch>;
 | 
						friend struct std::default_delete<TriggerMatch>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Type of session stopped callback */
 | 
					/** Type of session stopped callback */
 | 
				
			||||||
typedef function<void()> SessionStoppedCallback;
 | 
					typedef std::function<void()> SessionStoppedCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Type of datafeed callback */
 | 
					/** Type of datafeed callback */
 | 
				
			||||||
typedef function<void(shared_ptr<Device>, shared_ptr<Packet>)>
 | 
					typedef std::function<void(std::shared_ptr<Device>, std::shared_ptr<Packet>)>
 | 
				
			||||||
	DatafeedCallbackFunction;
 | 
						DatafeedCallbackFunction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Data required for C callback function to call a C++ datafeed callback */
 | 
					/* Data required for C callback function to call a C++ datafeed callback */
 | 
				
			||||||
| 
						 | 
					@ -597,7 +600,7 @@ class SR_API SessionDevice :
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit SessionDevice(struct sr_dev_inst *sdi);
 | 
						explicit SessionDevice(struct sr_dev_inst *sdi);
 | 
				
			||||||
	~SessionDevice();
 | 
						~SessionDevice();
 | 
				
			||||||
	shared_ptr<Device> get_shared_from_this();
 | 
						std::shared_ptr<Device> get_shared_from_this();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Session;
 | 
						friend class Session;
 | 
				
			||||||
	friend struct std::default_delete<SessionDevice>;
 | 
						friend struct std::default_delete<SessionDevice>;
 | 
				
			||||||
| 
						 | 
					@ -609,9 +612,9 @@ class SR_API Session : public UserOwned<Session>
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Add a device to this session.
 | 
						/** Add a device to this session.
 | 
				
			||||||
	 * @param device Device to add. */
 | 
						 * @param device Device to add. */
 | 
				
			||||||
	void add_device(shared_ptr<Device> device);
 | 
						void add_device(std::shared_ptr<Device> device);
 | 
				
			||||||
	/** List devices attached to this session. */
 | 
						/** List devices attached to this session. */
 | 
				
			||||||
	vector<shared_ptr<Device> > devices();
 | 
						std::vector<std::shared_ptr<Device> > devices();
 | 
				
			||||||
	/** Remove all devices from this session. */
 | 
						/** Remove all devices from this session. */
 | 
				
			||||||
	void remove_devices();
 | 
						void remove_devices();
 | 
				
			||||||
	/** Add a datafeed callback to this session.
 | 
						/** Add a datafeed callback to this session.
 | 
				
			||||||
| 
						 | 
					@ -630,27 +633,27 @@ public:
 | 
				
			||||||
	/** Set callback to be invoked on session stop. */
 | 
						/** Set callback to be invoked on session stop. */
 | 
				
			||||||
	void set_stopped_callback(SessionStoppedCallback callback);
 | 
						void set_stopped_callback(SessionStoppedCallback callback);
 | 
				
			||||||
	/** Get current trigger setting. */
 | 
						/** Get current trigger setting. */
 | 
				
			||||||
	shared_ptr<Trigger> trigger();
 | 
						std::shared_ptr<Trigger> trigger();
 | 
				
			||||||
	/** Get the context. */
 | 
						/** Get the context. */
 | 
				
			||||||
	shared_ptr<Context> context();
 | 
						std::shared_ptr<Context> context();
 | 
				
			||||||
	/** Set trigger setting.
 | 
						/** Set trigger setting.
 | 
				
			||||||
	 * @param trigger Trigger object to use. */
 | 
						 * @param trigger Trigger object to use. */
 | 
				
			||||||
	void set_trigger(shared_ptr<Trigger> trigger);
 | 
						void set_trigger(std::shared_ptr<Trigger> trigger);
 | 
				
			||||||
	/** Get filename this session was loaded from. */
 | 
						/** Get filename this session was loaded from. */
 | 
				
			||||||
	string filename() const;
 | 
						std::string filename() const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Session(shared_ptr<Context> context);
 | 
						explicit Session(std::shared_ptr<Context> context);
 | 
				
			||||||
	Session(shared_ptr<Context> context, string filename);
 | 
						Session(std::shared_ptr<Context> context, std::string filename);
 | 
				
			||||||
	~Session();
 | 
						~Session();
 | 
				
			||||||
	shared_ptr<Device> get_device(const struct sr_dev_inst *sdi);
 | 
						std::shared_ptr<Device> get_device(const struct sr_dev_inst *sdi);
 | 
				
			||||||
	struct sr_session *_structure;
 | 
						struct sr_session *_structure;
 | 
				
			||||||
	const shared_ptr<Context> _context;
 | 
						const std::shared_ptr<Context> _context;
 | 
				
			||||||
	map<const struct sr_dev_inst *, unique_ptr<SessionDevice> > _owned_devices;
 | 
						std::map<const struct sr_dev_inst *, std::unique_ptr<SessionDevice> > _owned_devices;
 | 
				
			||||||
	map<const struct sr_dev_inst *, shared_ptr<Device> > _other_devices;
 | 
						std::map<const struct sr_dev_inst *, std::shared_ptr<Device> > _other_devices;
 | 
				
			||||||
	vector<unique_ptr<DatafeedCallbackData> > _datafeed_callbacks;
 | 
						std::vector<std::unique_ptr<DatafeedCallbackData> > _datafeed_callbacks;
 | 
				
			||||||
	SessionStoppedCallback _stopped_callback;
 | 
						SessionStoppedCallback _stopped_callback;
 | 
				
			||||||
	string _filename;
 | 
						std::string _filename;
 | 
				
			||||||
	shared_ptr<Trigger> _trigger;
 | 
						std::shared_ptr<Trigger> _trigger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Context;
 | 
						friend class Context;
 | 
				
			||||||
	friend class DatafeedCallbackData;
 | 
						friend class DatafeedCallbackData;
 | 
				
			||||||
| 
						 | 
					@ -665,14 +668,14 @@ public:
 | 
				
			||||||
	/** Type of this packet. */
 | 
						/** Type of this packet. */
 | 
				
			||||||
	const PacketType *type() const;
 | 
						const PacketType *type() const;
 | 
				
			||||||
	/** Payload of this packet. */
 | 
						/** Payload of this packet. */
 | 
				
			||||||
	shared_ptr<PacketPayload> payload();
 | 
						std::shared_ptr<PacketPayload> payload();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	Packet(shared_ptr<Device> device,
 | 
						Packet(std::shared_ptr<Device> device,
 | 
				
			||||||
		const struct sr_datafeed_packet *structure);
 | 
							const struct sr_datafeed_packet *structure);
 | 
				
			||||||
	~Packet();
 | 
						~Packet();
 | 
				
			||||||
	const struct sr_datafeed_packet *_structure;
 | 
						const struct sr_datafeed_packet *_structure;
 | 
				
			||||||
	shared_ptr<Device> _device;
 | 
						std::shared_ptr<Device> _device;
 | 
				
			||||||
	unique_ptr<PacketPayload> _payload;
 | 
						std::unique_ptr<PacketPayload> _payload;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Session;
 | 
						friend class Session;
 | 
				
			||||||
	friend class Output;
 | 
						friend class Output;
 | 
				
			||||||
| 
						 | 
					@ -692,7 +695,7 @@ protected:
 | 
				
			||||||
	PacketPayload();
 | 
						PacketPayload();
 | 
				
			||||||
	virtual ~PacketPayload() = 0;
 | 
						virtual ~PacketPayload() = 0;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	virtual shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent) = 0;
 | 
						virtual std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent) = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Packet;
 | 
						friend class Packet;
 | 
				
			||||||
	friend class Output;
 | 
						friend class Output;
 | 
				
			||||||
| 
						 | 
					@ -712,7 +715,7 @@ public:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Header(const struct sr_datafeed_header *structure);
 | 
						explicit Header(const struct sr_datafeed_header *structure);
 | 
				
			||||||
	~Header();
 | 
						~Header();
 | 
				
			||||||
	shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
 | 
						std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_datafeed_header *_structure;
 | 
						const struct sr_datafeed_header *_structure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -726,14 +729,14 @@ class SR_API Meta :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/* Mapping of (ConfigKey, value) pairs. */
 | 
						/* Mapping of (ConfigKey, value) pairs. */
 | 
				
			||||||
	map<const ConfigKey *, Glib::VariantBase> config() const;
 | 
						std::map<const ConfigKey *, Glib::VariantBase> config() const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Meta(const struct sr_datafeed_meta *structure);
 | 
						explicit Meta(const struct sr_datafeed_meta *structure);
 | 
				
			||||||
	~Meta();
 | 
						~Meta();
 | 
				
			||||||
	shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
 | 
						std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_datafeed_meta *_structure;
 | 
						const struct sr_datafeed_meta *_structure;
 | 
				
			||||||
	map<const ConfigKey *, Glib::VariantBase> _config;
 | 
						std::map<const ConfigKey *, Glib::VariantBase> _config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Packet;
 | 
						friend class Packet;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -753,11 +756,13 @@ public:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Logic(const struct sr_datafeed_logic *structure);
 | 
						explicit Logic(const struct sr_datafeed_logic *structure);
 | 
				
			||||||
	~Logic();
 | 
						~Logic();
 | 
				
			||||||
	shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
 | 
						std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_datafeed_logic *_structure;
 | 
						const struct sr_datafeed_logic *_structure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Packet;
 | 
						friend class Packet;
 | 
				
			||||||
 | 
						friend class Analog;
 | 
				
			||||||
 | 
						friend struct std::default_delete<Logic>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Payload of a datafeed packet with analog data */
 | 
					/** Payload of a datafeed packet with analog data */
 | 
				
			||||||
| 
						 | 
					@ -776,7 +781,7 @@ public:
 | 
				
			||||||
	/** Number of samples in this packet. */
 | 
						/** Number of samples in this packet. */
 | 
				
			||||||
	unsigned int num_samples() const;
 | 
						unsigned int num_samples() const;
 | 
				
			||||||
	/** Channels for which this packet contains data. */
 | 
						/** Channels for which this packet contains data. */
 | 
				
			||||||
	vector<shared_ptr<Channel> > channels();
 | 
						std::vector<std::shared_ptr<Channel> > channels();
 | 
				
			||||||
	/** Size of a single sample in bytes. */
 | 
						/** Size of a single sample in bytes. */
 | 
				
			||||||
	unsigned int unitsize() const;
 | 
						unsigned int unitsize() const;
 | 
				
			||||||
	/** Samples use a signed data type. */
 | 
						/** Samples use a signed data type. */
 | 
				
			||||||
| 
						 | 
					@ -794,19 +799,47 @@ public:
 | 
				
			||||||
	/** TBD */
 | 
						/** TBD */
 | 
				
			||||||
	bool is_digits_decimal() const;
 | 
						bool is_digits_decimal() const;
 | 
				
			||||||
	/** TBD */
 | 
						/** TBD */
 | 
				
			||||||
	shared_ptr<Rational> scale();
 | 
						std::shared_ptr<Rational> scale();
 | 
				
			||||||
	/** TBD */
 | 
						/** TBD */
 | 
				
			||||||
	shared_ptr<Rational> offset();
 | 
						std::shared_ptr<Rational> offset();
 | 
				
			||||||
	/** Measured quantity of the samples in this packet. */
 | 
						/** Measured quantity of the samples in this packet. */
 | 
				
			||||||
	const Quantity *mq() const;
 | 
						const Quantity *mq() const;
 | 
				
			||||||
	/** Unit of the samples in this packet. */
 | 
						/** Unit of the samples in this packet. */
 | 
				
			||||||
	const Unit *unit() const;
 | 
						const Unit *unit() const;
 | 
				
			||||||
	/** Measurement flags associated with the samples in this packet. */
 | 
						/** Measurement flags associated with the samples in this packet. */
 | 
				
			||||||
	vector<const QuantityFlag *> mq_flags() const;
 | 
						std::vector<const QuantityFlag *> mq_flags() const;
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Provides a Logic packet that contains a conversion of the analog
 | 
				
			||||||
 | 
						 * data using a simple threshold.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param threshold Threshold to use.
 | 
				
			||||||
 | 
						 * @param data_ptr Pointer to num_samples() bytes where the logic
 | 
				
			||||||
 | 
						 *                 samples are stored. When nullptr, memory for
 | 
				
			||||||
 | 
						 *                 logic->data_pointer() will be allocated and must
 | 
				
			||||||
 | 
						 *                 be freed by the caller.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						std::shared_ptr<Logic> get_logic_via_threshold(float threshold,
 | 
				
			||||||
 | 
							uint8_t *data_ptr=nullptr) const;
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Provides a Logic packet that contains a conversion of the analog
 | 
				
			||||||
 | 
						 * data using a Schmitt-Trigger.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param lo_thr Low threshold to use (anything below this is low).
 | 
				
			||||||
 | 
						 * @param hi_thr High threshold to use (anything above this is high).
 | 
				
			||||||
 | 
						 * @param state Points to a byte that contains the current state of the
 | 
				
			||||||
 | 
						 *              converter. For best results, set to value of logic
 | 
				
			||||||
 | 
						 *              sample n-1.
 | 
				
			||||||
 | 
						 * @param data_ptr Pointer to num_samples() bytes where the logic
 | 
				
			||||||
 | 
						 *                 samples are stored. When nullptr, memory for
 | 
				
			||||||
 | 
						 *                 logic->data_pointer() will be allocated and must be
 | 
				
			||||||
 | 
						 *                 freed by the caller.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						std::shared_ptr<Logic> get_logic_via_schmitt_trigger(float lo_thr,
 | 
				
			||||||
 | 
							float hi_thr, uint8_t *state, uint8_t *data_ptr=nullptr) const;
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Analog(const struct sr_datafeed_analog *structure);
 | 
						explicit Analog(const struct sr_datafeed_analog *structure);
 | 
				
			||||||
	~Analog();
 | 
						~Analog();
 | 
				
			||||||
	shared_ptr<PacketPayload> share_owned_by(shared_ptr<Packet> parent);
 | 
						std::shared_ptr<PacketPayload> share_owned_by(std::shared_ptr<Packet> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_datafeed_analog *_structure;
 | 
						const struct sr_datafeed_analog *_structure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -827,7 +860,7 @@ public:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit Rational(const struct sr_rational *structure);
 | 
						explicit Rational(const struct sr_rational *structure);
 | 
				
			||||||
	~Rational();
 | 
						~Rational();
 | 
				
			||||||
	shared_ptr<Rational> share_owned_by(shared_ptr<Analog> parent);
 | 
						std::shared_ptr<Rational> share_owned_by(std::shared_ptr<Analog> parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_rational *_structure;
 | 
						const struct sr_rational *_structure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -841,18 +874,18 @@ class SR_API InputFormat :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Name of this input format. */
 | 
						/** Name of this input format. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** Description of this input format. */
 | 
						/** Description of this input format. */
 | 
				
			||||||
	string description() const;
 | 
						std::string description() const;
 | 
				
			||||||
	/** A list of preferred file name extensions for this file format.
 | 
						/** A list of preferred file name extensions for this file format.
 | 
				
			||||||
	 * @note This list is a recommendation only. */
 | 
						 * @note This list is a recommendation only. */
 | 
				
			||||||
	vector<string> extensions() const;
 | 
						std::vector<std::string> extensions() const;
 | 
				
			||||||
	/** Options supported by this input format. */
 | 
						/** Options supported by this input format. */
 | 
				
			||||||
	map<string, shared_ptr<Option> > options();
 | 
						std::map<std::string, std::shared_ptr<Option> > options();
 | 
				
			||||||
	/** Create an input using this input format.
 | 
						/** Create an input using this input format.
 | 
				
			||||||
	 * @param options Mapping of (option name, value) pairs. */
 | 
						 * @param options Mapping of (option name, value) pairs. */
 | 
				
			||||||
	shared_ptr<Input> create_input(map<string, Glib::VariantBase>
 | 
						std::shared_ptr<Input> create_input(std::map<std::string, Glib::VariantBase>
 | 
				
			||||||
			options = map<string, Glib::VariantBase>());
 | 
								options = std::map<std::string, Glib::VariantBase>());
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	explicit InputFormat(const struct sr_input_module *structure);
 | 
						explicit InputFormat(const struct sr_input_module *structure);
 | 
				
			||||||
	~InputFormat();
 | 
						~InputFormat();
 | 
				
			||||||
| 
						 | 
					@ -869,7 +902,7 @@ class SR_API Input : public UserOwned<Input>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Virtual device associated with this input. */
 | 
						/** Virtual device associated with this input. */
 | 
				
			||||||
	shared_ptr<InputDevice> device();
 | 
						std::shared_ptr<InputDevice> device();
 | 
				
			||||||
	/** Send next stream data.
 | 
						/** Send next stream data.
 | 
				
			||||||
	 * @param data Next stream data.
 | 
						 * @param data Next stream data.
 | 
				
			||||||
	 * @param length Length of data. */
 | 
						 * @param length Length of data. */
 | 
				
			||||||
| 
						 | 
					@ -878,11 +911,11 @@ public:
 | 
				
			||||||
	void end();
 | 
						void end();
 | 
				
			||||||
	void reset();
 | 
						void reset();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	Input(shared_ptr<Context> context, const struct sr_input *structure);
 | 
						Input(std::shared_ptr<Context> context, const struct sr_input *structure);
 | 
				
			||||||
	~Input();
 | 
						~Input();
 | 
				
			||||||
	const struct sr_input *_structure;
 | 
						const struct sr_input *_structure;
 | 
				
			||||||
	shared_ptr<Context> _context;
 | 
						std::shared_ptr<Context> _context;
 | 
				
			||||||
	unique_ptr<InputDevice> _device;
 | 
						std::unique_ptr<InputDevice> _device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class Context;
 | 
						friend class Context;
 | 
				
			||||||
	friend class InputFormat;
 | 
						friend class InputFormat;
 | 
				
			||||||
| 
						 | 
					@ -895,10 +928,10 @@ class SR_API InputDevice :
 | 
				
			||||||
	public Device
 | 
						public Device
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	InputDevice(shared_ptr<Input> input, struct sr_dev_inst *sdi);
 | 
						InputDevice(std::shared_ptr<Input> input, struct sr_dev_inst *sdi);
 | 
				
			||||||
	~InputDevice();
 | 
						~InputDevice();
 | 
				
			||||||
	shared_ptr<Device> get_shared_from_this();
 | 
						std::shared_ptr<Device> get_shared_from_this();
 | 
				
			||||||
	shared_ptr<Input> _input;
 | 
						std::shared_ptr<Input> _input;
 | 
				
			||||||
	friend class Input;
 | 
						friend class Input;
 | 
				
			||||||
	friend struct std::default_delete<InputDevice>;
 | 
						friend struct std::default_delete<InputDevice>;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -908,21 +941,23 @@ class SR_API Option : public UserOwned<Option>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Short name of this option suitable for command line usage. */
 | 
						/** Short name of this option suitable for command line usage. */
 | 
				
			||||||
	string id() const;
 | 
						std::string id() const;
 | 
				
			||||||
	/** Short name of this option suitable for GUI usage. */
 | 
						/** Short name of this option suitable for GUI usage. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** Description of this option in a sentence. */
 | 
						/** Description of this option in a sentence. */
 | 
				
			||||||
	string description() const;
 | 
						std::string description() const;
 | 
				
			||||||
	/** Default value for this option. */
 | 
						/** Default value for this option. */
 | 
				
			||||||
	Glib::VariantBase default_value() const;
 | 
						Glib::VariantBase default_value() const;
 | 
				
			||||||
	/** Possible values for this option, if a limited set. */
 | 
						/** Possible values for this option, if a limited set. */
 | 
				
			||||||
	vector<Glib::VariantBase> values() const;
 | 
						std::vector<Glib::VariantBase> values() const;
 | 
				
			||||||
 | 
						/** Parse a string argument into the appropriate type for this option. */
 | 
				
			||||||
 | 
						Glib::VariantBase parse_string(std::string value);
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	Option(const struct sr_option *structure,
 | 
						Option(const struct sr_option *structure,
 | 
				
			||||||
		shared_ptr<const struct sr_option *> structure_array);
 | 
							std::shared_ptr<const struct sr_option *> structure_array);
 | 
				
			||||||
	~Option();
 | 
						~Option();
 | 
				
			||||||
	const struct sr_option *_structure;
 | 
						const struct sr_option *_structure;
 | 
				
			||||||
	shared_ptr<const struct sr_option *> _structure_array;
 | 
						std::shared_ptr<const struct sr_option *> _structure_array;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class InputFormat;
 | 
						friend class InputFormat;
 | 
				
			||||||
	friend class OutputFormat;
 | 
						friend class OutputFormat;
 | 
				
			||||||
| 
						 | 
					@ -935,26 +970,26 @@ class SR_API OutputFormat :
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Name of this output format. */
 | 
						/** Name of this output format. */
 | 
				
			||||||
	string name() const;
 | 
						std::string name() const;
 | 
				
			||||||
	/** Description of this output format. */
 | 
						/** Description of this output format. */
 | 
				
			||||||
	string description() const;
 | 
						std::string description() const;
 | 
				
			||||||
	/** A list of preferred file name extensions for this file format.
 | 
						/** A list of preferred file name extensions for this file format.
 | 
				
			||||||
	 * @note This list is a recommendation only. */
 | 
						 * @note This list is a recommendation only. */
 | 
				
			||||||
	vector<string> extensions() const;
 | 
						std::vector<std::string> extensions() const;
 | 
				
			||||||
	/** Options supported by this output format. */
 | 
						/** Options supported by this output format. */
 | 
				
			||||||
	map<string, shared_ptr<Option> > options();
 | 
						std::map<std::string, std::shared_ptr<Option> > options();
 | 
				
			||||||
	/** Create an output using this format.
 | 
						/** Create an output using this format.
 | 
				
			||||||
	 * @param device Device to output for.
 | 
						 * @param device Device to output for.
 | 
				
			||||||
	 * @param options Mapping of (option name, value) pairs. */
 | 
						 * @param options Mapping of (option name, value) pairs. */
 | 
				
			||||||
	shared_ptr<Output> create_output(shared_ptr<Device> device,
 | 
						std::shared_ptr<Output> create_output(std::shared_ptr<Device> device,
 | 
				
			||||||
		map<string, Glib::VariantBase> options = map<string, Glib::VariantBase>());
 | 
							std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
 | 
				
			||||||
	/** Create an output using this format.
 | 
						/** Create an output using this format.
 | 
				
			||||||
	 * @param filename Name of destination file.
 | 
						 * @param filename Name of destination file.
 | 
				
			||||||
	 * @param device Device to output for.
 | 
						 * @param device Device to output for.
 | 
				
			||||||
	 * @param options Mapping of (option name, value) pairs. */
 | 
						 * @param options Mapping of (option name, value) pairs. */
 | 
				
			||||||
	shared_ptr<Output> create_output(string filename,
 | 
						std::shared_ptr<Output> create_output(std::string filename,
 | 
				
			||||||
		shared_ptr<Device> device,
 | 
							std::shared_ptr<Device> device,
 | 
				
			||||||
		map<string, Glib::VariantBase> options = map<string, Glib::VariantBase>());
 | 
							std::map<std::string, Glib::VariantBase> options = std::map<std::string, Glib::VariantBase>());
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Checks whether a given flag is set.
 | 
						 * Checks whether a given flag is set.
 | 
				
			||||||
	 * @param flag Flag to check
 | 
						 * @param flag Flag to check
 | 
				
			||||||
| 
						 | 
					@ -979,19 +1014,21 @@ class SR_API Output : public UserOwned<Output>
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	/** Update output with data from the given packet.
 | 
						/** Update output with data from the given packet.
 | 
				
			||||||
	 * @param packet Packet to handle. */
 | 
						 * @param packet Packet to handle. */
 | 
				
			||||||
	string receive(shared_ptr<Packet> packet);
 | 
						std::string receive(std::shared_ptr<Packet> packet);
 | 
				
			||||||
 | 
						/** Output format in use for this output */
 | 
				
			||||||
 | 
						std::shared_ptr<OutputFormat> format();
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	Output(shared_ptr<OutputFormat> format, shared_ptr<Device> device);
 | 
						Output(std::shared_ptr<OutputFormat> format, std::shared_ptr<Device> device);
 | 
				
			||||||
	Output(shared_ptr<OutputFormat> format,
 | 
						Output(std::shared_ptr<OutputFormat> format,
 | 
				
			||||||
		shared_ptr<Device> device, map<string, Glib::VariantBase> options);
 | 
							std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
 | 
				
			||||||
	Output(string filename, shared_ptr<OutputFormat> format,
 | 
						Output(std::string filename, std::shared_ptr<OutputFormat> format,
 | 
				
			||||||
		shared_ptr<Device> device, map<string, Glib::VariantBase> options);
 | 
							std::shared_ptr<Device> device, std::map<std::string, Glib::VariantBase> options);
 | 
				
			||||||
	~Output();
 | 
						~Output();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const struct sr_output *_structure;
 | 
						const struct sr_output *_structure;
 | 
				
			||||||
	const shared_ptr<OutputFormat> _format;
 | 
						const std::shared_ptr<OutputFormat> _format;
 | 
				
			||||||
	const shared_ptr<Device> _device;
 | 
						const std::shared_ptr<Device> _device;
 | 
				
			||||||
	const map<string, Glib::VariantBase> _options;
 | 
						const std::map<std::string, Glib::VariantBase> _options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	friend class OutputFormat;
 | 
						friend class OutputFormat;
 | 
				
			||||||
	friend struct std::default_delete<Output>;
 | 
						friend struct std::default_delete<Output>;
 | 
				
			||||||
| 
						 | 
					@ -1007,7 +1044,7 @@ public:
 | 
				
			||||||
		return static_cast<int>(_id);
 | 
							return static_cast<int>(_id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/** The name associated with this value. */
 | 
						/** The name associated with this value. */
 | 
				
			||||||
	string name() const
 | 
						std::string name() const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return _name;
 | 
							return _name;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1037,7 +1074,7 @@ protected:
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	static const std::map<const Enum, const Class * const> _values;
 | 
						static const std::map<const Enum, const Class * const> _values;
 | 
				
			||||||
	const Enum _id;
 | 
						const Enum _id;
 | 
				
			||||||
	const string _name;
 | 
						const std::string _name;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -94,10 +94,18 @@ VECTOR(std::shared_ptr<sigrok::HardwareDevice>, HardwareDevice)
 | 
				
			||||||
  "java.util.Map<JKey, JValue>"
 | 
					  "java.util.Map<JKey, JValue>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%typemap(javain,
 | 
					%typemap(javain,
 | 
				
			||||||
 | 
					/* SWIG 4.0.0 changed the std::map wrappers in an incompatible way. */
 | 
				
			||||||
 | 
					#if SWIG_VERSION >= 0x040000
 | 
				
			||||||
 | 
					    pre="  $javaclassname temp$javainput = new $javaclassname();
 | 
				
			||||||
 | 
					    for (java.util.Map.Entry<JKey, JValue> entry : $javainput.entrySet())
 | 
				
			||||||
 | 
					      temp$javainput.put(entry.getKey(), entry.getValue());",
 | 
				
			||||||
 | 
					    pgcppname="temp$javainput")
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
    pre="  $javaclassname temp$javainput = new $javaclassname();
 | 
					    pre="  $javaclassname temp$javainput = new $javaclassname();
 | 
				
			||||||
    for (java.util.Map.Entry<JKey, JValue> entry : $javainput.entrySet())
 | 
					    for (java.util.Map.Entry<JKey, JValue> entry : $javainput.entrySet())
 | 
				
			||||||
      temp$javainput.set(entry.getKey(), entry.getValue());",
 | 
					      temp$javainput.set(entry.getKey(), entry.getValue());",
 | 
				
			||||||
    pgcppname="temp$javainput")
 | 
					    pgcppname="temp$javainput")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  std::map< CKey, CValue > "$javaclassname.getCPtr(temp$javainput)"
 | 
					  std::map< CKey, CValue > "$javaclassname.getCPtr(temp$javainput)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%typemap(javaout) std::map< CKey, CValue > {
 | 
					%typemap(javaout) std::map< CKey, CValue > {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -45,6 +45,8 @@ which provides access to the error code and description."
 | 
				
			||||||
%module(docstring=DOCSTRING) classes
 | 
					%module(docstring=DOCSTRING) classes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%{
 | 
					%{
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <pygobject.h>
 | 
					#include <pygobject.h>
 | 
				
			||||||
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 | 
					#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
 | 
				
			||||||
| 
						 | 
					@ -53,8 +55,6 @@ which provides access to the error code and description."
 | 
				
			||||||
PyObject *PyGObject_lib;
 | 
					PyObject *PyGObject_lib;
 | 
				
			||||||
PyObject *GLib;
 | 
					PyObject *GLib;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if PYGOBJECT_FLAGS_SIGNED
 | 
					#if PYGOBJECT_FLAGS_SIGNED
 | 
				
			||||||
typedef gint pyg_flags_type;
 | 
					typedef gint pyg_flags_type;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
| 
						 | 
					@ -112,6 +112,9 @@ typedef guint pyg_flags_type;
 | 
				
			||||||
    g_free(value);
 | 
					    g_free(value);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Use the same typemap above for Glib::VariantContainerBase */
 | 
				
			||||||
 | 
					%apply Glib::VariantBase { Glib::VariantContainerBase }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Map from callable PyObject to LogCallbackFunction */
 | 
					/* Map from callable PyObject to LogCallbackFunction */
 | 
				
			||||||
%typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
 | 
					%typecheck(SWIG_TYPECHECK_POINTER) sigrok::LogCallbackFunction {
 | 
				
			||||||
    $1 = PyCallable_Check($input);
 | 
					    $1 = PyCallable_Check($input);
 | 
				
			||||||
| 
						 | 
					@ -337,7 +340,14 @@ Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::Config
 | 
				
			||||||
        return Glib::Variant<double>::create(PyFloat_AsDouble(input));
 | 
					        return Glib::Variant<double>::create(PyFloat_AsDouble(input));
 | 
				
			||||||
    else if (type == SR_T_INT32 && PyInt_Check(input))
 | 
					    else if (type == SR_T_INT32 && PyInt_Check(input))
 | 
				
			||||||
        return Glib::Variant<gint32>::create(PyInt_AsLong(input));
 | 
					        return Glib::Variant<gint32>::create(PyInt_AsLong(input));
 | 
				
			||||||
    else
 | 
					    else if ((type == SR_T_RATIONAL_VOLT) && PyTuple_Check(input) && (PyTuple_Size(input) == 2)) {
 | 
				
			||||||
 | 
					        PyObject *numObj = PyTuple_GetItem(input, 0);
 | 
				
			||||||
 | 
					        PyObject *denomObj = PyTuple_GetItem(input, 1);
 | 
				
			||||||
 | 
					        if ((PyInt_Check(numObj) || PyLong_Check(numObj)) && (PyInt_Check(denomObj) || PyLong_Check(denomObj))) {
 | 
				
			||||||
 | 
					          const std::vector<guint64> v = {(guint64)PyInt_AsLong(numObj), (guint64)PyInt_AsLong(denomObj)};
 | 
				
			||||||
 | 
					          return Glib::Variant< std::vector<guint64> >::create(v);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    throw sigrok::Error(SR_ERR_ARG);
 | 
					    throw sigrok::Error(SR_ERR_ARG);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -390,6 +400,7 @@ std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Ignore these methods, we will override them below. */
 | 
					/* Ignore these methods, we will override them below. */
 | 
				
			||||||
%ignore sigrok::Analog::data;
 | 
					%ignore sigrok::Analog::data;
 | 
				
			||||||
 | 
					%ignore sigrok::Logic::data;
 | 
				
			||||||
%ignore sigrok::Driver::scan;
 | 
					%ignore sigrok::Driver::scan;
 | 
				
			||||||
%ignore sigrok::InputFormat::create_input;
 | 
					%ignore sigrok::InputFormat::create_input;
 | 
				
			||||||
%ignore sigrok::OutputFormat::create_output;
 | 
					%ignore sigrok::OutputFormat::create_output;
 | 
				
			||||||
| 
						 | 
					@ -548,4 +559,42 @@ std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return NumPy array from Logic::data(). */
 | 
				
			||||||
 | 
					%extend sigrok::Logic
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PyObject * _data()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        npy_intp dims[2];
 | 
				
			||||||
 | 
					        dims[0] = $self->data_length() / $self->unit_size();
 | 
				
			||||||
 | 
					        dims[1] = $self->unit_size();
 | 
				
			||||||
 | 
					        int typenum = NPY_UINT8;
 | 
				
			||||||
 | 
					        void *data = $self->data_pointer();
 | 
				
			||||||
 | 
					        return PyArray_SimpleNewFromData(2, dims, typenum, data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%pythoncode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    data = property(_data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Create logic packet from Python buffer. */
 | 
				
			||||||
 | 
					%extend sigrok::Context
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::shared_ptr<Packet> _create_logic_packet_buf(PyObject *buf, unsigned int unit_size)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Py_buffer view;
 | 
				
			||||||
 | 
					        PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE);
 | 
				
			||||||
 | 
					        return $self->create_logic_packet(view.buf, view.len, unit_size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%pythoncode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    def _Context_create_logic_packet(self, buf, unit_size):
 | 
				
			||||||
 | 
					        return self._create_logic_packet_buf(buf, unit_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Context.create_logic_packet = _Context_create_logic_packet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%include "doc_end.i"
 | 
					%include "doc_end.i"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,10 +41,10 @@ which provides access to the error code and description."
 | 
				
			||||||
%module(docstring=DOCSTRING) sigrok
 | 
					%module(docstring=DOCSTRING) sigrok
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%{
 | 
					%{
 | 
				
			||||||
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <glibmm.h>
 | 
					#include <glibmm.h>
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "config.h"
 | 
					 | 
				
			||||||
%}
 | 
					%}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%include "../swig/templates.i"
 | 
					%include "../swig/templates.i"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ for compound in index.findall('compound'):
 | 
				
			||||||
        if language == 'python':
 | 
					        if language == 'python':
 | 
				
			||||||
            print('%%feature("docstring") %s "%s";' % (class_name, brief))
 | 
					            print('%%feature("docstring") %s "%s";' % (class_name, brief))
 | 
				
			||||||
        elif language == 'ruby':
 | 
					        elif language == 'ruby':
 | 
				
			||||||
            print('%%feature("docstring") %s "/* Document-class: %s\\n%s */\\n";' % (class_name, class_name.replace("sigrok", "Sigrok", 1), brief))
 | 
					            print('%%feature("docstring") %s "Document-class: %s\\n%s\\n";' % (class_name, class_name.replace("sigrok", "Sigrok", 1), brief))
 | 
				
			||||||
        elif language == 'java':
 | 
					        elif language == 'java':
 | 
				
			||||||
            print('%%typemap(javaclassmodifiers) %s "/** %s */\npublic class"' % (
 | 
					            print('%%typemap(javaclassmodifiers) %s "/** %s */\npublic class"' % (
 | 
				
			||||||
            class_name, brief))
 | 
					            class_name, brief))
 | 
				
			||||||
| 
						 | 
					@ -77,10 +77,10 @@ for compound in index.findall('compound'):
 | 
				
			||||||
                            for name, desc in parameters.items()]) + '";')
 | 
					                            for name, desc in parameters.items()]) + '";')
 | 
				
			||||||
                if language == 'ruby' and kind == 'public-func':
 | 
					                if language == 'ruby' and kind == 'public-func':
 | 
				
			||||||
                    print(str.join('\n', [
 | 
					                    print(str.join('\n', [
 | 
				
			||||||
                        '%%feature("docstring") %s::%s "/* %s' % (
 | 
					                        '%%feature("docstring") %s::%s "%s' % (
 | 
				
			||||||
                            class_name, member_name, brief)] + [
 | 
					                            class_name, member_name, brief)] + [
 | 
				
			||||||
                        '@param %s %s' % (name, desc)
 | 
					                        '@param %s %s' % (name, desc)
 | 
				
			||||||
                            for name, desc in parameters.items()]) + ' */\\n";')
 | 
					                            for name, desc in parameters.items()]) + '\\n";')
 | 
				
			||||||
                elif language == 'java' and kind == 'public-func':
 | 
					                elif language == 'java' and kind == 'public-func':
 | 
				
			||||||
                        print(str.join('\n', [
 | 
					                        print(str.join('\n', [
 | 
				
			||||||
                            '%%javamethodmodifiers %s::%s "/** %s' % (
 | 
					                            '%%javamethodmodifiers %s::%s "/** %s' % (
 | 
				
			||||||
| 
						 | 
					@ -111,4 +111,4 @@ for compound in index.findall('compound'):
 | 
				
			||||||
            print('%}')
 | 
					            print('%}')
 | 
				
			||||||
    elif language == 'ruby' and constants:
 | 
					    elif language == 'ruby' and constants:
 | 
				
			||||||
        for member_name, brief in constants:
 | 
					        for member_name, brief in constants:
 | 
				
			||||||
            print('%%feature("docstring") %s::%s "/* %s */\\n";' % (class_name, member_name, brief))
 | 
					            print('%%feature("docstring") %s::%s "%s\\n";' % (class_name, member_name, brief))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										167
									
								
								configure.ac
								
								
								
								
							
							
						
						
									
										167
									
								
								configure.ac
								
								
								
								
							| 
						 | 
					@ -96,11 +96,18 @@ SR_PKGLIBS_RUBY=
 | 
				
			||||||
SR_EXTRA_LIBS=
 | 
					SR_EXTRA_LIBS=
 | 
				
			||||||
SR_EXTRA_CXX_LIBS=
 | 
					SR_EXTRA_CXX_LIBS=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_ARG_OPT_PKG([libserialport], [LIBSERIALPORT], [NEED_SERIAL],
 | 
					SR_ARG_OPT_PKG([libserialport], [LIBSERIALPORT], ,
 | 
				
			||||||
	[libserialport >= 0.1.1])
 | 
						[libserialport >= 0.1.1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_ARG_OPT_PKG([libftdi], [LIBFTDI],,
 | 
					SR_ARG_OPT_PKG([libftdi], [LIBFTDI], , [libftdi1 >= 1.0])
 | 
				
			||||||
	[libftdi1 >= 1.0], [libftdi >= 0.16])
 | 
					
 | 
				
			||||||
 | 
					# pkg-config file names: MinGW/MacOSX: hidapi; Linux: hidapi-hidraw/-libusb
 | 
				
			||||||
 | 
					SR_ARG_OPT_PKG([libhidapi], [LIBHIDAPI], ,
 | 
				
			||||||
 | 
						[hidapi >= 0.8.0], [hidapi-hidraw >= 0.8.0], [hidapi-libusb >= 0.8.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_ARG_OPT_PKG([libbluez], [LIBBLUEZ], , [bluez >= 4.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_ARG_OPT_PKG([libnettle], [LIBNETTLE], , [nettle])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# FreeBSD comes with an "integrated" libusb-1.0-style USB API.
 | 
					# FreeBSD comes with an "integrated" libusb-1.0-style USB API.
 | 
				
			||||||
# This means libusb-1.0 is always available; no need to check for it.
 | 
					# This means libusb-1.0 is always available; no need to check for it.
 | 
				
			||||||
| 
						 | 
					@ -131,6 +138,25 @@ SR_ARG_OPT_CHECK([libieee1284], [LIBIEEE1284],, [
 | 
				
			||||||
AS_IF([test "x$sr_have_libieee1284" = xyes],
 | 
					AS_IF([test "x$sr_have_libieee1284" = xyes],
 | 
				
			||||||
	[SR_PREPEND([SR_EXTRA_LIBS], [-lieee1284])])
 | 
						[SR_PREPEND([SR_EXTRA_LIBS], [-lieee1284])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_ARG_OPT_PKG([libgio], [LIBGIO], , [gio-2.0 >= 2.24.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See if any of the (potentially platform specific) libs are available
 | 
				
			||||||
 | 
					# which provide some means of Bluetooth communication.
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_libbluez" = xyes],
 | 
				
			||||||
 | 
						sr_have_bluetooth=yes, sr_have_bluetooth=no)
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_bluetooth" = xyes],
 | 
				
			||||||
 | 
						[AC_DEFINE([HAVE_BLUETOOTH], [1], [Specifies whether Bluetooth communication is supported.])])
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_bluetooth" = xyes],
 | 
				
			||||||
 | 
						[SR_APPEND([sr_deps_avail], [bluetooth_comm])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_libserialport" = xyes -o "x$sr_have_libhidapi" = xyes -o "x$sr_have_bluetooth" = xyes],
 | 
				
			||||||
 | 
						sr_have_serial_comm=yes, sr_have_serial_comm=no)
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_serial_comm" = xyes],
 | 
				
			||||||
 | 
						[AC_DEFINE([HAVE_SERIAL_COMM], [1], [Specifies whether serial communication is supported.])])
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_have_serial_comm" = xyes],
 | 
				
			||||||
 | 
						[SR_APPEND([sr_deps_avail], [serial_comm])])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([NEED_SERIAL], [test "x$sr_have_serial_comm" = xyes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
######################
 | 
					######################
 | 
				
			||||||
##  Feature checks  ##
 | 
					##  Feature checks  ##
 | 
				
			||||||
######################
 | 
					######################
 | 
				
			||||||
| 
						 | 
					@ -162,13 +188,25 @@ AS_CASE([$host_os], [mingw*], [SR_PREPEND([SR_EXTRA_LIBS], [-lws2_32])])
 | 
				
			||||||
SR_SEARCH_LIBS([SR_EXTRA_LIBS], [pow], [m])
 | 
					SR_SEARCH_LIBS([SR_EXTRA_LIBS], [pow], [m])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# RPC is only needed for VXI support.
 | 
					# RPC is only needed for VXI support.
 | 
				
			||||||
AC_CACHE_CHECK([for RPC support], [sr_cv_have_rpc],
 | 
					AC_CACHE_CHECK([for SunRPC support], [sr_cv_have_sunrpc],
 | 
				
			||||||
	[AC_LINK_IFELSE([AC_LANG_PROGRAM(
 | 
						[AC_LINK_IFELSE([AC_LANG_PROGRAM(
 | 
				
			||||||
			[[#include <rpc/rpc.h>]m4_newline[CLIENT *rpc_test(void);]],
 | 
								[[#include <rpc/rpc.h>]m4_newline[CLIENT *rpc_test(void);]],
 | 
				
			||||||
			[[(void) clnt_create("", 0, 0, "");]])],
 | 
								[[(void) clnt_create("", 0, 0, "");]])],
 | 
				
			||||||
		[sr_cv_have_rpc=yes], [sr_cv_have_rpc=no])])
 | 
							[RPC_CFLAGS=""; RPC_LIBS=""; sr_cv_have_sunrpc=yes],
 | 
				
			||||||
 | 
							[sr_cv_have_sunrpc=no])])
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES([TIRPC],
 | 
				
			||||||
 | 
						[libtirpc],
 | 
				
			||||||
 | 
						[RPC_CFLAGS=$TIRPC_CFLAGS; SR_PREPEND([SR_EXTRA_LIBS], [$TIRPC_LIBS]); sr_cv_have_tirpc=yes],
 | 
				
			||||||
 | 
						[sr_cv_have_tirpc=no])
 | 
				
			||||||
 | 
					AS_IF([test "x$sr_cv_have_sunrpc" = xyes -o "x$sr_cv_have_tirpc" = xyes],
 | 
				
			||||||
 | 
						[sr_cv_have_rpc=yes], [sr_cv_have_rpc=no])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_SUBST(RPC_CFLAGS)
 | 
				
			||||||
 | 
					AC_SUBST(RPC_LIBS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AS_IF([test "x$sr_cv_have_rpc" = xyes],
 | 
					AS_IF([test "x$sr_cv_have_rpc" = xyes],
 | 
				
			||||||
	[AC_DEFINE([HAVE_RPC], [1], [Specifies whether we have RPC support.])])
 | 
						[AC_DEFINE([HAVE_RPC], [1], [Specifies whether we have RPC support (either by SunRPC or libtirpc).])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# VXI support is only compiled if RPC support was found.
 | 
					# VXI support is only compiled if RPC support was found.
 | 
				
			||||||
AM_CONDITIONAL([NEED_RPC], [test "x$sr_cv_have_rpc" = xyes])
 | 
					AM_CONDITIONAL([NEED_RPC], [test "x$sr_cv_have_rpc" = xyes])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,62 +257,83 @@ m4_define([_SR_DRIVER], [
 | 
				
			||||||
m4_define([SR_DRIVER],
 | 
					m4_define([SR_DRIVER],
 | 
				
			||||||
	[_SR_DRIVER([$1], [$2], m4_expand([AS_TR_CPP([HW_$2])]), [$3])])
 | 
						[_SR_DRIVER([$1], [$2], m4_expand([AS_TR_CPP([HW_$2])]), [$3])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_DRIVER([Agilent DMM], [agilent-dmm], [libserialport])
 | 
					SR_DRIVER([Agilent DMM], [agilent-dmm], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Appa 55II], [appa-55ii], [libserialport])
 | 
					SR_DRIVER([Appa 55II], [appa-55ii], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Arachnid Labs Re:load Pro], [arachnid-labs-re-load-pro], [libserialport])
 | 
					SR_DRIVER([Arachnid Labs Re:load Pro], [arachnid-labs-re-load-pro], [serial_comm])
 | 
				
			||||||
SR_DRIVER([ASIX SIGMA/SIGMA2], [asix-sigma], [libftdi])
 | 
					SR_DRIVER([ASIX SIGMA/SIGMA2], [asix-sigma], [libftdi])
 | 
				
			||||||
SR_DRIVER([Atten PPS3xxx], [atten-pps3xxx], [libserialport])
 | 
					SR_DRIVER([Atten PPS3xxx], [atten-pps3xxx], [serial_comm])
 | 
				
			||||||
SR_DRIVER([BayLibre ACME], [baylibre-acme], [sys_timerfd_h])
 | 
					SR_DRIVER([BayLibre ACME], [baylibre-acme], [sys_timerfd_h])
 | 
				
			||||||
SR_DRIVER([BeagleLogic], [beaglelogic], [sys_mman_h sys_ioctl_h])
 | 
					SR_DRIVER([BeagleLogic], [beaglelogic], [sys_mman_h sys_ioctl_h])
 | 
				
			||||||
SR_DRIVER([Brymen BM86x], [brymen-bm86x], [libusb])
 | 
					SR_DRIVER([CEM DT-885x], [cem-dt-885x], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Brymen DMM], [brymen-dmm], [libserialport])
 | 
					SR_DRIVER([Center 3xx], [center-3xx], [serial_comm])
 | 
				
			||||||
SR_DRIVER([CEM DT-885x], [cem-dt-885x], [libserialport])
 | 
					 | 
				
			||||||
SR_DRIVER([Center 3xx], [center-3xx], [libserialport])
 | 
					 | 
				
			||||||
SR_DRIVER([ChronoVu LA], [chronovu-la], [libusb libftdi])
 | 
					SR_DRIVER([ChronoVu LA], [chronovu-la], [libusb libftdi])
 | 
				
			||||||
SR_DRIVER([Colead SLM], [colead-slm], [libserialport])
 | 
					SR_DRIVER([Colead SLM], [colead-slm], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Conrad DIGI 35 CPU], [conrad-digi-35-cpu], [libserialport])
 | 
					SR_DRIVER([Conrad DIGI 35 CPU], [conrad-digi-35-cpu], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([dcttech usbrelay], [dcttech-usbrelay], [libhidapi])
 | 
				
			||||||
SR_DRIVER([demo], [demo])
 | 
					SR_DRIVER([demo], [demo])
 | 
				
			||||||
SR_DRIVER([Fluke DMM], [fluke-dmm], [libserialport])
 | 
					SR_DRIVER([DreamSourceLab DSLogic], [dreamsourcelab-dslogic], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([Fluke 45], [fluke-45])
 | 
				
			||||||
 | 
					SR_DRIVER([Fluke DMM], [fluke-dmm], [serial_comm])
 | 
				
			||||||
SR_DRIVER([FTDI LA], [ftdi-la], [libusb libftdi])
 | 
					SR_DRIVER([FTDI LA], [ftdi-la], [libusb libftdi])
 | 
				
			||||||
SR_DRIVER([fx2lafw], [fx2lafw], [libusb])
 | 
					SR_DRIVER([fx2lafw], [fx2lafw], [libusb])
 | 
				
			||||||
SR_DRIVER([GMC MH 1x/2x], [gmc-mh-1x-2x], [libserialport])
 | 
					SR_DRIVER([GMC MH 1x/2x], [gmc-mh-1x-2x], [serial_comm])
 | 
				
			||||||
SR_DRIVER([GW Instek GDS-800], [gwinstek-gds-800], [libserialport])
 | 
					SR_DRIVER([GW Instek GDS-800], [gwinstek-gds-800], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Hameg HMO], [hameg-hmo], [libserialport])
 | 
					SR_DRIVER([GW Instek GPD], [gwinstek-gpd], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([Hameg HMO], [hameg-hmo], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([Hantek 4032L], [hantek-4032l], [libusb])
 | 
				
			||||||
SR_DRIVER([Hantek 6xxx], [hantek-6xxx], [libusb])
 | 
					SR_DRIVER([Hantek 6xxx], [hantek-6xxx], [libusb])
 | 
				
			||||||
SR_DRIVER([Hantek DSO], [hantek-dso], [libusb])
 | 
					SR_DRIVER([Hantek DSO], [hantek-dso], [libusb])
 | 
				
			||||||
SR_DRIVER([HP 3457A], [hp-3457a])
 | 
					SR_DRIVER([HP 3457A], [hp-3457a])
 | 
				
			||||||
 | 
					SR_DRIVER([HP 3478A], [hp-3478a], [libgpib])
 | 
				
			||||||
 | 
					SR_DRIVER([hp-59306a], [hp-59306a])
 | 
				
			||||||
SR_DRIVER([Hung-Chang DSO-2100], [hung-chang-dso-2100], [libieee1284])
 | 
					SR_DRIVER([Hung-Chang DSO-2100], [hung-chang-dso-2100], [libieee1284])
 | 
				
			||||||
SR_DRIVER([Ikalogic Scanalogic-2], [ikalogic-scanalogic2], [libusb])
 | 
					SR_DRIVER([Ikalogic Scanalogic-2], [ikalogic-scanalogic2], [libusb])
 | 
				
			||||||
SR_DRIVER([Ikalogic Scanaplus], [ikalogic-scanaplus], [libftdi])
 | 
					SR_DRIVER([Ikalogic Scanaplus], [ikalogic-scanaplus], [libftdi])
 | 
				
			||||||
 | 
					SR_DRIVER([Ikalogic ScanaQuad], [ikalogic-scanaquad], [libftdi])
 | 
				
			||||||
 | 
					SR_DRIVER([IPDBG LA], [ipdbg-la])
 | 
				
			||||||
 | 
					SR_DRIVER([ITECH IT8500], [itech-it8500], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Kecheng KC-330B], [kecheng-kc-330b], [libusb])
 | 
					SR_DRIVER([Kecheng KC-330B], [kecheng-kc-330b], [libusb])
 | 
				
			||||||
SR_DRIVER([KERN scale], [kern-scale], [libserialport])
 | 
					SR_DRIVER([KERN scale], [kern-scale], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Korad KAxxxxP], [korad-kaxxxxp], [libserialport])
 | 
					SR_DRIVER([Kingst LA2016], [kingst-la2016], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([Korad KAxxxxP], [korad-kaxxxxp], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Lascar EL-USB], [lascar-el-usb], [libusb])
 | 
					SR_DRIVER([Lascar EL-USB], [lascar-el-usb], [libusb])
 | 
				
			||||||
SR_DRIVER([LeCroy LogicStudio], [lecroy-logicstudio], [libusb])
 | 
					SR_DRIVER([LeCroy LogicStudio], [lecroy-logicstudio], [libusb])
 | 
				
			||||||
SR_DRIVER([LeCroy X-Stream], [lecroy-xstream])
 | 
					SR_DRIVER([LeCroy X-Stream], [lecroy-xstream])
 | 
				
			||||||
SR_DRIVER([Manson HCS-3xxx], [manson-hcs-3xxx], [libserialport])
 | 
					SR_DRIVER([Manson HCS-3xxx], [manson-hcs-3xxx], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([Mastech MS6514], [mastech-ms6514], [serial_comm])
 | 
				
			||||||
SR_DRIVER([maynuo-m97], [maynuo-m97])
 | 
					SR_DRIVER([maynuo-m97], [maynuo-m97])
 | 
				
			||||||
SR_DRIVER([MIC 985xx], [mic-985xx], [libserialport])
 | 
					SR_DRIVER([MIC 985xx], [mic-985xx], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Motech LPS 30x], [motech-lps-30x], [libserialport])
 | 
					SR_DRIVER([Microchip PICkit2], [microchip-pickit2], [libusb])
 | 
				
			||||||
SR_DRIVER([Norma DMM], [norma-dmm], [libserialport])
 | 
					SR_DRIVER([Mooshimeter DMM], [mooshimeter-dmm], [bluetooth_comm libgio])
 | 
				
			||||||
SR_DRIVER([OpenBench Logic Sniffer], [openbench-logic-sniffer], [libserialport])
 | 
					SR_DRIVER([Motech LPS 30x], [motech-lps-30x], [serial_comm])
 | 
				
			||||||
SR_DRIVER([PCE PCE-322A], [pce-322a], [libserialport])
 | 
					SR_DRIVER([Norma DMM], [norma-dmm], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([OpenBench Logic Sniffer], [openbench-logic-sniffer], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([PCE PCE-322A], [pce-322a], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Pipistrello-OLS], [pipistrello-ols], [libftdi])
 | 
					SR_DRIVER([Pipistrello-OLS], [pipistrello-ols], [libftdi])
 | 
				
			||||||
 | 
					SR_DRIVER([RDTech DPSxxxx/DPHxxxx], [rdtech-dps], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([RDTech UMXX], [rdtech-um], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([RDTech TCXX], [rdtech-tc], [serial_comm libnettle])
 | 
				
			||||||
SR_DRIVER([Rigol DS], [rigol-ds])
 | 
					SR_DRIVER([Rigol DS], [rigol-ds])
 | 
				
			||||||
SR_DRIVER([Rohde&Schwarz SME-0x], [rohde-schwarz-sme-0x], [libserialport])
 | 
					SR_DRIVER([Rigol DG], [rigol-dg])
 | 
				
			||||||
 | 
					SR_DRIVER([Rohde&Schwarz SME-0x], [rohde-schwarz-sme-0x], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Saleae Logic16], [saleae-logic16], [libusb])
 | 
					SR_DRIVER([Saleae Logic16], [saleae-logic16], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([Saleae Logic Pro], [saleae-logic-pro], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([SCPI DMM], [scpi-dmm])
 | 
				
			||||||
SR_DRIVER([SCPI PPS], [scpi-pps])
 | 
					SR_DRIVER([SCPI PPS], [scpi-pps])
 | 
				
			||||||
SR_DRIVER([serial DMM], [serial-dmm], [libserialport])
 | 
					SR_DRIVER([serial DMM], [serial-dmm], [serial_comm])
 | 
				
			||||||
SR_DRIVER([serial LCR], [serial-lcr], [libserialport])
 | 
					SR_DRIVER([serial LCR], [serial-lcr], [serial_comm])
 | 
				
			||||||
 | 
					SR_DRIVER([Siglent SDS], [siglent-sds])
 | 
				
			||||||
SR_DRIVER([Sysclk LWLA], [sysclk-lwla], [libusb])
 | 
					SR_DRIVER([Sysclk LWLA], [sysclk-lwla], [libusb])
 | 
				
			||||||
SR_DRIVER([Teleinfo], [teleinfo], [libserialport])
 | 
					SR_DRIVER([Sysclk SLA5032], [sysclk-sla5032], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([Teleinfo], [teleinfo], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Testo], [testo], [libusb])
 | 
					SR_DRIVER([Testo], [testo], [libusb])
 | 
				
			||||||
SR_DRIVER([Tondaj SL-814], [tondaj-sl-814], [libserialport])
 | 
					SR_DRIVER([Tondaj SL-814], [tondaj-sl-814], [serial_comm])
 | 
				
			||||||
SR_DRIVER([UNI-T DMM], [uni-t-dmm], [libusb])
 | 
					SR_DRIVER([UNI-T DMM], [uni-t-dmm], [libusb])
 | 
				
			||||||
SR_DRIVER([UNI-T UT32x], [uni-t-ut32x], [libusb])
 | 
					SR_DRIVER([UNI-T UT181A], [uni-t-ut181a], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Victor DMM], [victor-dmm], [libusb])
 | 
					SR_DRIVER([UNI-T UT32x], [uni-t-ut32x], [serial_comm])
 | 
				
			||||||
SR_DRIVER([Yokogawa DL/DLM], [yokogawa-dlm])
 | 
					SR_DRIVER([Yokogawa DL/DLM], [yokogawa-dlm])
 | 
				
			||||||
SR_DRIVER([ZEROPLUS Logic Cube], [zeroplus-logic-cube], [libusb])
 | 
					SR_DRIVER([ZEROPLUS Logic Cube], [zeroplus-logic-cube], [libusb])
 | 
				
			||||||
 | 
					SR_DRIVER([ZKETECH EBD-USB], [zketech-ebd-usb], [serial_comm])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
###############################
 | 
					###############################
 | 
				
			||||||
##  Language bindings setup  ##
 | 
					##  Language bindings setup  ##
 | 
				
			||||||
| 
						 | 
					@ -398,7 +457,7 @@ AS_IF([test "x$HAVE_PYMOD_NUMPY" != xyes],
 | 
				
			||||||
	[SR_APPEND([sr_python_missing], [', '], [numpy])])
 | 
						[SR_APPEND([sr_python_missing], [', '], [numpy])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The Python bindings use SWIG to generate code.
 | 
					# The Python bindings use SWIG to generate code.
 | 
				
			||||||
AC_CHECK_PROGS([SWIG], [swig swig3.0 swig2.0])
 | 
					AC_CHECK_PROGS([SWIG], [swig swig4.0 swig3.0 swig2.0])
 | 
				
			||||||
AS_IF([test "x$SWIG" != x],
 | 
					AS_IF([test "x$SWIG" != x],
 | 
				
			||||||
    AC_MSG_CHECKING([for $SWIG version])
 | 
					    AC_MSG_CHECKING([for $SWIG version])
 | 
				
			||||||
    [SWIG_VERSION=`$SWIG -version 2>&1 | sed -n 's/SWIG Version //p'`]
 | 
					    [SWIG_VERSION=`$SWIG -version 2>&1 | sed -n 's/SWIG Version //p'`]
 | 
				
			||||||
| 
						 | 
					@ -436,8 +495,8 @@ sr_rbminor=${sr_rbminor%%.*}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The Ruby bindings need Ruby development files.
 | 
					# The Ruby bindings need Ruby development files.
 | 
				
			||||||
SR_PKG_CHECK([ruby_dev], [SR_PKGLIBS_RUBY],
 | 
					SR_PKG_CHECK([ruby_dev], [SR_PKGLIBS_RUBY],
 | 
				
			||||||
	[ruby],
 | 
						[ruby >= 2.5.0],
 | 
				
			||||||
	[ruby-$sr_rbmajor.$sr_rbminor])
 | 
						[ruby-$sr_rbmajor.$sr_rbminor >= 2.5.0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AS_IF([test "x$sr_have_ruby_dev" != xyes],
 | 
					AS_IF([test "x$sr_have_ruby_dev" != xyes],
 | 
				
			||||||
	[SR_APPEND([sr_ruby_missing], [', '], [Headers])])
 | 
						[SR_APPEND([sr_ruby_missing], [', '], [Headers])])
 | 
				
			||||||
| 
						 | 
					@ -589,10 +648,19 @@ Detected libraries (optional):
 | 
				
			||||||
$sr_pkglibs_summary
 | 
					$sr_pkglibs_summary
 | 
				
			||||||
Enabled hardware drivers:
 | 
					Enabled hardware drivers:
 | 
				
			||||||
$sr_driver_summary
 | 
					$sr_driver_summary
 | 
				
			||||||
 | 
					Enabled serial communication transports:
 | 
				
			||||||
 | 
					  - serial comm ................... $sr_have_serial_comm
 | 
				
			||||||
 | 
					  - libserialport ................. $sr_have_libserialport
 | 
				
			||||||
 | 
					  - hidapi ........................ $sr_have_libhidapi
 | 
				
			||||||
 | 
					  - bluetooth ..................... $sr_have_bluetooth
 | 
				
			||||||
 | 
					  - bluez ......................... $sr_have_libbluez
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Enabled SCPI backends:
 | 
					Enabled SCPI backends:
 | 
				
			||||||
 - TCP............................. yes
 | 
					 - TCP............................. yes
 | 
				
			||||||
 | 
					 - SunRPC ......................... $sr_cv_have_sunrpc
 | 
				
			||||||
 | 
					 - TI-RPC ......................... $sr_cv_have_tirpc
 | 
				
			||||||
 - RPC............................. $sr_cv_have_rpc
 | 
					 - RPC............................. $sr_cv_have_rpc
 | 
				
			||||||
 - serial.......................... $sr_have_libserialport
 | 
					 - serial.......................... $sr_have_serial_comm
 | 
				
			||||||
 - VISA............................ $sr_have_librevisa
 | 
					 - VISA............................ $sr_have_librevisa
 | 
				
			||||||
 - GPIB............................ $sr_have_libgpib
 | 
					 - GPIB............................ $sr_have_libgpib
 | 
				
			||||||
 - USBTMC.......................... $sr_have_libusb
 | 
					 - USBTMC.......................... $sr_have_libusb
 | 
				
			||||||
| 
						 | 
					@ -604,3 +672,24 @@ Enabled language bindings:
 | 
				
			||||||
 - Java............................ $BINDINGS_JAVA$sr_report_java
 | 
					 - Java............................ $BINDINGS_JAVA$sr_report_java
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_EOF
 | 
					_EOF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Emit a warning if the C++ bindings are not being built.
 | 
				
			||||||
 | 
					AM_COND_IF([BINDINGS_CXX], [], [
 | 
				
			||||||
 | 
					cat >&AS_MESSAGE_FD <<_EOF
 | 
				
			||||||
 | 
					===============================================================================
 | 
				
			||||||
 | 
					WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 | 
				
			||||||
 | 
					===============================================================================
 | 
				
			||||||
 | 
					===                                                                         ===
 | 
				
			||||||
 | 
					===         The libsigrok C++ bindings are not being built since you        ===
 | 
				
			||||||
 | 
					===             are missing one or more dependencies (see above)!           ===
 | 
				
			||||||
 | 
					===                                                                         ===
 | 
				
			||||||
 | 
					===      This means you won't be able to compile frontends that require     ===
 | 
				
			||||||
 | 
					===  the C++ bindings (such as PulseView)! You also won't be able to build  ===
 | 
				
			||||||
 | 
					===     other bindings and frontends using those (such as sigrok-meter)!    ===
 | 
				
			||||||
 | 
					===                                                                         ===
 | 
				
			||||||
 | 
					===============================================================================
 | 
				
			||||||
 | 
					WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 | 
				
			||||||
 | 
					===============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_EOF
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,354 @@
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## Copyright (C) 2010-2013 Uwe Hermann <uwe@hermann-uwe.de>
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					## it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					## the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					## (at your option) any later version.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					## GNU General Public License for more details.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					## along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# These rules do not grant any permission by itself, but flag devices
 | 
				
			||||||
 | 
					# supported by libsigrok.
 | 
				
			||||||
 | 
					# The access policy is stored in the 61-libsigrok-plugdev.rules and
 | 
				
			||||||
 | 
					# 61-libsigrok-uaccess.rules.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Note: Any syntax changes here will need to be tested against the
 | 
				
			||||||
 | 
					# 'update-device-filter' Makefile target in the sigrok-androidutils
 | 
				
			||||||
 | 
					# repo, since that parses this file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please keep this list sorted alphabetically by vendor/device name.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACTION!="add|change", GOTO="libsigrok_rules_end"
 | 
				
			||||||
 | 
					SUBSYSTEM!="usb|usbmisc|usb_device|hidraw", GOTO="libsigrok_rules_end"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Agilent USBTMC-connected devices
 | 
				
			||||||
 | 
					# 34405A
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0618", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# 34410A
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0607", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# 34460A
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0957", ATTRS{idProduct}=="1b07", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# DSO1000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0588", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# MSO7000A series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0957", ATTRS{idProduct}=="1735", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ASIX SIGMA
 | 
				
			||||||
 | 
					# ASIX SIGMA2
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="a600", ATTRS{idProduct}=="a000", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Braintechnology USB-LPS
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0498", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Brymen BU-86X adapter (e.g. for Brymen BM867/BM869 and possibly others).
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0820", ATTRS{idProduct}=="0001", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ChronoVu LA8 (new VID/PID)
 | 
				
			||||||
 | 
					# ChronoVu LA16 (new VID/PID)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8867", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CWAV USBee AX
 | 
				
			||||||
 | 
					# ARMFLY AX-Pro (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# ARMFLY Mini-Logic (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# EE Electronics ESLA201A (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# HT USBee-AxPro (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# MCU123 USBee AX Pro clone (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# Noname LHT00SU1 (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					# XZL_Studio AX (clone of the CWAV USBee AX)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0014", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CWAV USBee DX
 | 
				
			||||||
 | 
					# HT USBee-DxPro (clone of the CWAV USBee DX), not yet supported!
 | 
				
			||||||
 | 
					# XZL_Studio DX (clone of the CWAV USBee DX)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0015", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CWAV USBee SX
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0009", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CWAV USBee ZX
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0005", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cypress FX2 eval boards without EEPROM:
 | 
				
			||||||
 | 
					# Lcsoft Mini Board
 | 
				
			||||||
 | 
					# Braintechnology USB Interface V2.x
 | 
				
			||||||
 | 
					# fx2grok-tiny
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="8613", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dangerous Prototypes Buspirate (v3)
 | 
				
			||||||
 | 
					# ChronoVu LA8 (old VID/PID)
 | 
				
			||||||
 | 
					# ChronoVu LA16 (old VID/PID)
 | 
				
			||||||
 | 
					# ftdi-la (FT232R)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Dangerous Prototypes Buspirate (v4)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb00", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dcttech.com USB relay card, and other V-USB based firmware
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# DreamSourceLab DSLogic
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0001", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# DreamSourceLab DSLogic Pro
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0003", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# DreamSourceLab DScope
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0002", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# DreamSourceLab DSLogic Plus
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0020", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					# DreamSourceLab DSLogic Basic
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0021", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# GW-Instek GDM-9061 (USBTMC mode)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2184", ATTRS{idProduct}=="0059", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# HAMEG HO720
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="ed72", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# HAMEG HO730
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="ed73", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek DSO-2090
 | 
				
			||||||
 | 
					# lsusb: "04b4:2090 Cypress Semiconductor Corp."
 | 
				
			||||||
 | 
					# lsusb after FW upload: "04b5:2090 ROHM LSI Systems USA, LLC"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2090", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2090", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek DSO-2150
 | 
				
			||||||
 | 
					# lsusb: "04b4:2150 Cypress Semiconductor Corp."
 | 
				
			||||||
 | 
					# lsusb after FW upload: "04b5:2150 ROHM LSI Systems USA, LLC"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2150", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2150", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek DSO-2250
 | 
				
			||||||
 | 
					# lsusb: "04b4:2250 Cypress Semiconductor Corp."
 | 
				
			||||||
 | 
					# lsusb after FW upload: "04b5:2250 ROHM LSI Systems USA, LLC"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2250", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2250", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek DSO-5200
 | 
				
			||||||
 | 
					# lsusb: "04b4:5200 Cypress Semiconductor Corp."
 | 
				
			||||||
 | 
					# lsusb after FW upload: "04b5:5200 ROHM LSI Systems USA, LLC"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="5200", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="5200", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek DSO-5200A
 | 
				
			||||||
 | 
					# lsusb: "04b4:520a Cypress Semiconductor Corp."
 | 
				
			||||||
 | 
					# lsusb after FW upload: "04b5:520a ROHM LSI Systems USA, LLC"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="520a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="520a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek 6022BE, renumerates as 1d50:608e "sigrok fx2lafw", Serial: Hantek 6022BE
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="6022", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek 6022BL, renumerates as 1d50:608e "sigrok fx2lafw", Serial: Hantek 6022BL
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="602a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Hantek 4032L
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="4032", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IKALOGIC Scanalogic-2
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="4123", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# IKALOGIC ScanaPLUS
 | 
				
			||||||
 | 
					# ftdi-la (FT232H)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ftdi-la (TIAO USB Multi Protocol Adapter (TUMPA))
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Kecheng KC-330B
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1041", ATTRS{idProduct}=="8101", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Keysight USBTMC-connected devices
 | 
				
			||||||
 | 
					# 34465A
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2a8d", ATTRS{idProduct}=="0101", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Kingst LA2016
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="77a1", ATTRS{idProduct}=="01a2", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Lascar Electronics EL-USB-2
 | 
				
			||||||
 | 
					# Lascar Electronics EL-USB-CO
 | 
				
			||||||
 | 
					# This is actually the generic SiLabs (Cygnal) F32x USBXpress VID:PID.
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="0002", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LeCroy LogicStudio16
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="05ff", ATTRS{idProduct}=="a001", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="05ff", ATTRS{idProduct}=="a002", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LeCroy WaveRunner
 | 
				
			||||||
 | 
					# 05ff:1023: 625Zi
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="05ff", ATTRS{idProduct}=="1023", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Link Instruments MSO-19
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="3195", ATTRS{idProduct}=="f190", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Logic Shrimp
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fa95", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MiniLA Mockup
 | 
				
			||||||
 | 
					# ftdi-la (FT2232H)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ftdi-la (FT4232H)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# MIC 98581
 | 
				
			||||||
 | 
					# MIC 98583
 | 
				
			||||||
 | 
					# Tondaj SL-814
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Microchip PICkit2
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="0033", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Openbench Logic Sniffer
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="000a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DS1000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0588", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol 1000Z series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="04ce", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DS2000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="04b0", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DS4000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="04b1", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DG4000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0641", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DG1000z series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0642", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DG800 and DG900 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0643", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol DP800 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0e11", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rigol MSO5000 series
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0515", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Rohde&Schwarz HMO series mixed-signal oscilloscope (previously branded Hameg) VCP/USBTMC mode
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0117", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0119", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sainsmart DDS120 / Rocktech BM102, renumerates as 1d50:608e "sigrok fx2lafw", Serial: Sainsmart DDS120
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="8102", ATTRS{idProduct}=="8102", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Saleae Logic
 | 
				
			||||||
 | 
					# EE Electronics ESLA100 (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					# Hantek 6022BL in LA mode (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					# Instrustar ISDS205X in LA mode (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					# Robomotic MiniLogic (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					# Robomotic BugLogic 3 (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					# MCU123 Saleae Logic clone (clone of the Saleae Logic)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0925", ATTRS{idProduct}=="3881", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Saleae Logic16
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="21a9", ATTRS{idProduct}=="1001", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Saleae Logic Pro 16
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="21a9", ATTRS{idProduct}=="1006", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Siglent USBTMC devices.
 | 
				
			||||||
 | 
					# f4ec:ee3a: E.g. SDS1052DL+ scope
 | 
				
			||||||
 | 
					# f4ec:ee38: E.g. SDS1104X-E scope
 | 
				
			||||||
 | 
					# f4ed:ee3a: E.g. SDS1202X-E scope or SDG1010 waveform generator
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="f4ec", ATTRS{idProduct}=="ee3a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="f4ed", ATTRS{idProduct}=="ee3a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# sigrok FX2 LA (8ch)
 | 
				
			||||||
 | 
					# fx2grok-flat (before and after renumeration)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608c", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# sigrok FX2 LA (16ch)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608d", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# sigrok FX2 DSO (2ch)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608e", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# sigrok usb-c-grok
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608f", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SiLabs CP210x (USB CDC) UART bridge, used (among others) in:
 | 
				
			||||||
 | 
					# CEM DT-8852
 | 
				
			||||||
 | 
					# Manson HCS-3202
 | 
				
			||||||
 | 
					# MASTECH MS2115B
 | 
				
			||||||
 | 
					# MASTECH MS5308
 | 
				
			||||||
 | 
					# MASTECH MS8250D
 | 
				
			||||||
 | 
					# PeakTech 3330
 | 
				
			||||||
 | 
					# Voltcraft PPS-11815
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SiLabs CP2110 (USB HID) UART bridge, used (among others) in:
 | 
				
			||||||
 | 
					# UNI-T UT612
 | 
				
			||||||
 | 
					# UNI-T UT-D09 multimeter cable (for various UNI-T and rebranded DMMs)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea80", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sysclk LWLA1016
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2961", ATTRS{idProduct}=="6688", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sysclk LWLA1034
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2961", ATTRS{idProduct}=="6689", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sysclk SLA5032 ("32CH 500M" mode)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="2961", ATTRS{idProduct}=="66b0", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Testo 435
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="128d", ATTRS{idProduct}=="0003", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# UNI-T UT-D04 multimeter cable (for various UNI-T and rebranded DMMs)
 | 
				
			||||||
 | 
					# UNI-T UT325
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="e008", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# V&A VA4000 multimeter cable (for various V&A DMMs)
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="04fc", ATTRS{idProduct}=="0201", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Victor 70C
 | 
				
			||||||
 | 
					# Victor 86C
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="1244", ATTRS{idProduct}=="d237", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# YiXingDianZi MDSO
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="d4a2", ATTRS{idProduct}=="5660", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ZEROPLUS Logic Cube LAP-C series
 | 
				
			||||||
 | 
					# There are various devices in the ZEROPLUS Logic Cube series:
 | 
				
			||||||
 | 
					# 0c12:7002: LAP-16128U
 | 
				
			||||||
 | 
					# 0c12:7009: LAP-C(16064)
 | 
				
			||||||
 | 
					# 0c12:700a: LAP-C(16128)
 | 
				
			||||||
 | 
					# 0c12:700b: LAP-C(32128)
 | 
				
			||||||
 | 
					# 0c12:700c: LAP-C(321000)
 | 
				
			||||||
 | 
					# 0c12:700d: LAP-C(322000)
 | 
				
			||||||
 | 
					# 0c12:700e: LAP-C(16032)
 | 
				
			||||||
 | 
					# 0c12:7016: LAP-C(162000)
 | 
				
			||||||
 | 
					# 0c12:7025: LAP-C(16128+)
 | 
				
			||||||
 | 
					# 0c12:7100: AKIP-9101
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7002", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7007", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7009", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700a", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700b", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700c", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700d", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700e", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7016", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7025", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7100", ENV{ID_SIGROK}="1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LABEL="libsigrok_rules_end"
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## Copyright (C) 2017 Stefan Bruens <stefan.bruens@rwth-aachen.de>
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					## it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					## the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					## (at your option) any later version.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					## GNU General Public License for more details.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					## along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Grant access permissions to users who are in the "plugdev" group.
 | 
				
			||||||
 | 
					# "plugdev" is typically used on Debian based distributions and may not
 | 
				
			||||||
 | 
					# exist elsewhere.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This file, when installed, must be installed with a name lexicographically
 | 
				
			||||||
 | 
					# sorted later than the accompanied 60-libsigrok.rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACTION!="add|change", GOTO="libsigrok_rules_plugdev_end"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV{ID_SIGROK}=="1", MODE="660", GROUP="plugdev"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LABEL="libsigrok_rules_plugdev_end"
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## Copyright (C) 2017 Stefan Bruens <stefan.bruens@rwth-aachen.de>
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					## it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					## the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					## (at your option) any later version.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					## GNU General Public License for more details.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					## You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					## along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Grant access permissions to users who are currently logged in locally.
 | 
				
			||||||
 | 
					# This is the default policy for systems using systemd-logind (or a
 | 
				
			||||||
 | 
					# compatible replacement).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This file, when installed, must be installed with a name lexicographically
 | 
				
			||||||
 | 
					# sorted later than the accompanied 60-libsigrok.rules, and earlier than
 | 
				
			||||||
 | 
					# the systemd upstream 71-seat.rules.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ACTION!="add|change", GOTO="libsigrok_rules_uaccess_end"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV{ID_SIGROK}=="1", TAG+="uaccess"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LABEL="libsigrok_rules_uaccess_end"
 | 
				
			||||||
| 
						 | 
					@ -1,243 +0,0 @@
 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Copyright (C) 2010-2013 Uwe Hermann <uwe@hermann-uwe.de>
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## This program is free software; you can redistribute it and/or modify
 | 
					 | 
				
			||||||
## it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
## the Free Software Foundation; either version 2 of the License, or
 | 
					 | 
				
			||||||
## (at your option) any later version.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
## GNU General Public License for more details.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# NOTE: On a systemd based system, using tag=uaccess, this file _must_ be
 | 
					 | 
				
			||||||
# named/numbered to come before the seat rules are applied in 70-xxx.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
## Please keep this list sorted alphabetically by vendor/device name.
 | 
					 | 
				
			||||||
##
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ACTION!="add|change", GOTO="libsigrok_rules_end"
 | 
					 | 
				
			||||||
SUBSYSTEM!="usb|usbmisc|usb_device", GOTO="libsigrok_rules_end"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Agilent USBTMC-connected devices
 | 
					 | 
				
			||||||
# 34405A
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0618", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
# 34410A
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0607", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
# DSO1000 series
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0957", ATTRS{idProduct}=="0588", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# ASIX SIGMA
 | 
					 | 
				
			||||||
# ASIX SIGMA2
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="a600", ATTRS{idProduct}=="a000", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Braintechnology USB-LPS
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0498", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CEM DT-8852
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# ChronoVu LA8 (new VID/PID)
 | 
					 | 
				
			||||||
# ChronoVu LA16 (new VID/PID)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8867", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CWAV USBee AX
 | 
					 | 
				
			||||||
# ARMFLY AX-Pro (clone of the CWAV USBee AX)
 | 
					 | 
				
			||||||
# ARMFLY Mini-Logic (clone of the CWAV USBee AX)
 | 
					 | 
				
			||||||
# EE Electronics ESLA201A (clone of the CWAV USBee AX)
 | 
					 | 
				
			||||||
# MCU123 USBee AX Pro clone (clone of the CWAV USBee AX)
 | 
					 | 
				
			||||||
# XZL_Studio AX (clone of the CWAV USBee AX)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0014", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CWAV USBee DX
 | 
					 | 
				
			||||||
# XZL_Studio DX (clone of the CWAV USBee DX)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0015", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# CWAV USBee SX
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="08a9", ATTRS{idProduct}=="0009", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Cypress FX2 eval boards without EEPROM:
 | 
					 | 
				
			||||||
# Lcsoft Mini Board
 | 
					 | 
				
			||||||
# Braintechnology USB Interface V2.x
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="8613", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Dangerous Prototypes Buspirate (v3)
 | 
					 | 
				
			||||||
# ChronoVu LA8 (old VID/PID)
 | 
					 | 
				
			||||||
# ChronoVu LA16 (old VID/PID)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Dangerous Prototypes Buspirate (v4)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fb00", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# DreamSourceLab DSLogic
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0001", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
# DreamSourceLab DSLogic Pro
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
# DreamSourceLab DScope
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="2a0e", ATTRS{idProduct}=="0002", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HAMEG HO720
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="ed72", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# HAMEG HO730
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="ed73", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek DSO-2090
 | 
					 | 
				
			||||||
# lsusb: "04b4:2090 Cypress Semiconductor Corp."
 | 
					 | 
				
			||||||
# lsusb after FW upload: "04b5:2090 ROHM LSI Systems USA, LLC"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2090", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2090", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek DSO-2150
 | 
					 | 
				
			||||||
# lsusb: "04b4:2150 Cypress Semiconductor Corp."
 | 
					 | 
				
			||||||
# lsusb after FW upload: "04b5:2150 ROHM LSI Systems USA, LLC"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2150", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2150", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek DSO-2250
 | 
					 | 
				
			||||||
# lsusb: "04b4:2250 Cypress Semiconductor Corp."
 | 
					 | 
				
			||||||
# lsusb after FW upload: "04b5:2250 ROHM LSI Systems USA, LLC"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="2250", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="2250", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek DSO-5200
 | 
					 | 
				
			||||||
# lsusb: "04b4:5200 Cypress Semiconductor Corp."
 | 
					 | 
				
			||||||
# lsusb after FW upload: "04b5:5200 ROHM LSI Systems USA, LLC"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="5200", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="5200", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek DSO-5200A
 | 
					 | 
				
			||||||
# lsusb: "04b4:520a Cypress Semiconductor Corp."
 | 
					 | 
				
			||||||
# lsusb after FW upload: "04b5:520a ROHM LSI Systems USA, LLC"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="520a", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b5", ATTRS{idProduct}=="520a", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek 6022BE
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="6022", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608e", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Hantek 6022BL
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="602a", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608e", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# IKALOGIC Scanalogic-2
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="4123", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# IKALOGIC ScanaPLUS
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Kecheng KC-330B
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1041", ATTRS{idProduct}=="8101", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Lascar Electronics EL-USB-2
 | 
					 | 
				
			||||||
# Lascar Electronics EL-USB-CO
 | 
					 | 
				
			||||||
# This is actually the generic SiLabs (Cygnal) F32x USBXpress VID:PID.
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="0002", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# LeCroy LogicStudio16
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="05ff", ATTRS{idProduct}=="a001", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="05ff", ATTRS{idProduct}=="a002", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Link Instruments MSO-19
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="3195", ATTRS{idProduct}=="f190", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Logic Shrimp
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="fa95", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MiniLA Mockup
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# MIC 98581
 | 
					 | 
				
			||||||
# MIC 98583
 | 
					 | 
				
			||||||
# Tondaj SL-814
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Openbench Logic Sniffer
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="000a", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rigol DS1000 series
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0588", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rigol 1000Z series
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="04ce", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rigol DS2000 series
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="04b0", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rigol DG4000 series
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0641", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rohde&Schwarz HMO1002 Series VCP/USBTMC mode
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0119", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Sainsmart DDS120 / Rocktech BM102
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="8102", ATTRS{idProduct}=="8102", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608e", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Saleae Logic
 | 
					 | 
				
			||||||
# EE Electronics ESLA100 (clone of the Saleae Logic)
 | 
					 | 
				
			||||||
# Robomotic MiniLogic (clone of the Saleae Logic)
 | 
					 | 
				
			||||||
# Robomotic BugLogic 3 (clone of the Saleae Logic)
 | 
					 | 
				
			||||||
# MCU123 Saleae Logic clone (clone of the Saleae Logic)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0925", ATTRS{idProduct}=="3881", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Saleae Logic16
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="21a9", ATTRS{idProduct}=="1001", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# sigrok FX2 LA (8ch)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608c", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# sigrok FX2 LA (16ch)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608d", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SysClk LWLA1016
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="2961", ATTRS{idProduct}=="6688", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SysClk LWLA1034
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="2961", ATTRS{idProduct}=="6689", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Testo 435
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="128d", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# UNI-T UT-D04 multimeter cable (for various UNI-T and rebranded DMMs)
 | 
					 | 
				
			||||||
# http://sigrok.org/wiki/Device_cables#UNI-T_UT-D04
 | 
					 | 
				
			||||||
# UNI-T UT325
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="e008", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# V&A VA4000 multimeter cable (for various V&A DMMs)
 | 
					 | 
				
			||||||
# http://sigrok.org/wiki/Device_cables#V.26A_VA4000
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="04fc", ATTRS{idProduct}=="0201", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Victor 70C
 | 
					 | 
				
			||||||
# Victor 86C
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="1244", ATTRS{idProduct}=="d237", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# ZEROPLUS Logic Cube LAP-C series
 | 
					 | 
				
			||||||
# There are various devices in the ZEROPLUS Logic Cube series:
 | 
					 | 
				
			||||||
# 0c12:7002: LAP-16128U
 | 
					 | 
				
			||||||
# 0c12:7009: LAP-C(16064)
 | 
					 | 
				
			||||||
# 0c12:700a: LAP-C(16128)
 | 
					 | 
				
			||||||
# 0c12:700b: LAP-C(32128)
 | 
					 | 
				
			||||||
# 0c12:700c: LAP-C(321000)
 | 
					 | 
				
			||||||
# 0c12:700d: LAP-C(322000)
 | 
					 | 
				
			||||||
# 0c12:700e: LAP-C(16032)
 | 
					 | 
				
			||||||
# 0c12:7016: LAP-C(162000)
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7002", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7009", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700a", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700b", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700c", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700d", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="700e", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7016", MODE="660", GROUP="plugdev", TAG+="uaccess"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LABEL="libsigrok_rules_end"
 | 
					 | 
				
			||||||
| 
						 | 
					@ -80,15 +80,22 @@ enum sr_error_code {
 | 
				
			||||||
	/* Update sr_strerror()/sr_strerror_name() (error.c) upon changes! */
 | 
						/* Update sr_strerror()/sr_strerror_name() (error.c) upon changes! */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Ternary return type for DMM/LCR/etc packet parser validity checks. */
 | 
				
			||||||
 | 
					enum sr_valid_code {
 | 
				
			||||||
 | 
						SR_PACKET_INVALID = -1,	/**< Certainly invalid. */
 | 
				
			||||||
 | 
						SR_PACKET_VALID = 0,	/**< Certainly valid. */
 | 
				
			||||||
 | 
						SR_PACKET_NEED_RX = +1,	/**< Need more RX data. */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SR_MAX_CHANNELNAME_LEN 32
 | 
					#define SR_MAX_CHANNELNAME_LEN 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Handy little macros */
 | 
					/* Handy little macros */
 | 
				
			||||||
#define SR_HZ(n)  (n)
 | 
					#define SR_HZ(n)  (n)
 | 
				
			||||||
#define SR_KHZ(n) ((n) * (uint64_t)(1000ULL))
 | 
					#define SR_KHZ(n) ((n) * UINT64_C(1000))
 | 
				
			||||||
#define SR_MHZ(n) ((n) * (uint64_t)(1000000ULL))
 | 
					#define SR_MHZ(n) ((n) * UINT64_C(1000000))
 | 
				
			||||||
#define SR_GHZ(n) ((n) * (uint64_t)(1000000000ULL))
 | 
					#define SR_GHZ(n) ((n) * UINT64_C(1000000000))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SR_HZ_TO_NS(n) ((uint64_t)(1000000000ULL) / (n))
 | 
					#define SR_HZ_TO_NS(n) (UINT64_C(1000000000) / (n))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** libsigrok loglevels. */
 | 
					/** libsigrok loglevels. */
 | 
				
			||||||
enum sr_loglevel {
 | 
					enum sr_loglevel {
 | 
				
			||||||
| 
						 | 
					@ -233,6 +240,10 @@ enum sr_mq {
 | 
				
			||||||
	SR_MQ_MASS,
 | 
						SR_MQ_MASS,
 | 
				
			||||||
	/** Harmonic ratio */
 | 
						/** Harmonic ratio */
 | 
				
			||||||
	SR_MQ_HARMONIC_RATIO,
 | 
						SR_MQ_HARMONIC_RATIO,
 | 
				
			||||||
 | 
						/** Energy. */
 | 
				
			||||||
 | 
						SR_MQ_ENERGY,
 | 
				
			||||||
 | 
						/** Electric charge. */
 | 
				
			||||||
 | 
						SR_MQ_ELECTRIC_CHARGE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Update sr_key_info_mq[] (hwdriver.c) upon changes! */
 | 
						/* Update sr_key_info_mq[] (hwdriver.c) upon changes! */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -290,7 +301,7 @@ enum sr_unit {
 | 
				
			||||||
	SR_UNIT_VOLT_AMPERE,
 | 
						SR_UNIT_VOLT_AMPERE,
 | 
				
			||||||
	/** Real power [W]. */
 | 
						/** Real power [W]. */
 | 
				
			||||||
	SR_UNIT_WATT,
 | 
						SR_UNIT_WATT,
 | 
				
			||||||
	/** Consumption [Wh]. */
 | 
						/** Energy (consumption) in watt hour [Wh]. */
 | 
				
			||||||
	SR_UNIT_WATT_HOUR,
 | 
						SR_UNIT_WATT_HOUR,
 | 
				
			||||||
	/** Wind speed in meters per second. */
 | 
						/** Wind speed in meters per second. */
 | 
				
			||||||
	SR_UNIT_METER_SECOND,
 | 
						SR_UNIT_METER_SECOND,
 | 
				
			||||||
| 
						 | 
					@ -324,6 +335,12 @@ enum sr_unit {
 | 
				
			||||||
	SR_UNIT_TOLA,
 | 
						SR_UNIT_TOLA,
 | 
				
			||||||
	/** Pieces (number of items). */
 | 
						/** Pieces (number of items). */
 | 
				
			||||||
	SR_UNIT_PIECE,
 | 
						SR_UNIT_PIECE,
 | 
				
			||||||
 | 
						/** Energy in joule. */
 | 
				
			||||||
 | 
						SR_UNIT_JOULE,
 | 
				
			||||||
 | 
						/** Electric charge in coulomb. */
 | 
				
			||||||
 | 
						SR_UNIT_COULOMB,
 | 
				
			||||||
 | 
						/** Electric charge in ampere hour [Ah]. */
 | 
				
			||||||
 | 
						SR_UNIT_AMPERE_HOUR,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Update unit_strings[] (analog.c) and fancyprint() (output/analog.c)
 | 
						 * Update unit_strings[] (analog.c) and fancyprint() (output/analog.c)
 | 
				
			||||||
| 
						 | 
					@ -650,11 +667,11 @@ struct sr_key_info {
 | 
				
			||||||
/** Configuration capabilities. */
 | 
					/** Configuration capabilities. */
 | 
				
			||||||
enum sr_configcap {
 | 
					enum sr_configcap {
 | 
				
			||||||
	/** Value can be read. */
 | 
						/** Value can be read. */
 | 
				
			||||||
	SR_CONF_GET = (1 << 31),
 | 
						SR_CONF_GET = (1UL << 31),
 | 
				
			||||||
	/** Value can be written. */
 | 
						/** Value can be written. */
 | 
				
			||||||
	SR_CONF_SET = (1 << 30),
 | 
						SR_CONF_SET = (1UL << 30),
 | 
				
			||||||
	/** Possible values can be enumerated. */
 | 
						/** Possible values can be enumerated. */
 | 
				
			||||||
	SR_CONF_LIST = (1 << 29),
 | 
						SR_CONF_LIST = (1UL << 29),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Configuration keys */
 | 
					/** Configuration keys */
 | 
				
			||||||
| 
						 | 
					@ -703,6 +720,15 @@ enum sr_configkey {
 | 
				
			||||||
	/** The device can act as a function generator. */
 | 
						/** The device can act as a function generator. */
 | 
				
			||||||
	SR_CONF_SIGNAL_GENERATOR,
 | 
						SR_CONF_SIGNAL_GENERATOR,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** The device can measure power. */
 | 
				
			||||||
 | 
						SR_CONF_POWERMETER,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * The device can switch between multiple sources, e.g. a relay actuator
 | 
				
			||||||
 | 
						 * or multiplexer.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_MULTIPLEXER,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
						/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*--- Driver scan options -------------------------------------------*/
 | 
						/*--- Driver scan options -------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					@ -748,6 +774,16 @@ enum sr_configkey {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	SR_CONF_MODBUSADDR,
 | 
						SR_CONF_MODBUSADDR,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * User specified forced driver attachment to unknown devices.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * By design the interpretation of the string depends on the
 | 
				
			||||||
 | 
						 * specific driver. It typically would be either a replacement
 | 
				
			||||||
 | 
						 * '*IDN?' response value, or a sub-driver name. But could also
 | 
				
			||||||
 | 
						 * be anything else and totally arbitrary.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_FORCE_DETECT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
						/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*--- Device (or channel group) configuration -----------------------*/
 | 
						/*--- Device (or channel group) configuration -----------------------*/
 | 
				
			||||||
| 
						 | 
					@ -953,6 +989,8 @@ enum sr_configkey {
 | 
				
			||||||
	 * Channel regulation
 | 
						 * Channel regulation
 | 
				
			||||||
	 * get: "CV", "CC" or "UR", denoting constant voltage, constant current
 | 
						 * get: "CV", "CC" or "UR", denoting constant voltage, constant current
 | 
				
			||||||
	 *      or unregulated.
 | 
						 *      or unregulated.
 | 
				
			||||||
 | 
						 *      "CC-" denotes a power supply in current sink mode (e.g. HP 66xxB).
 | 
				
			||||||
 | 
						 *      "" is used when there is no regulation, e.g. the output is disabled.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	SR_CONF_REGULATION,
 | 
						SR_CONF_REGULATION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -983,6 +1021,68 @@ enum sr_configkey {
 | 
				
			||||||
	/** Trigger level. */
 | 
						/** Trigger level. */
 | 
				
			||||||
	SR_CONF_TRIGGER_LEVEL,
 | 
						SR_CONF_TRIGGER_LEVEL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Under-voltage condition threshold. */
 | 
				
			||||||
 | 
						SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Which external clock source to use if the device supports
 | 
				
			||||||
 | 
						 * multiple external clock channels.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_EXTERNAL_CLOCK_SOURCE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Offset of a source without strictly-defined MQ. */
 | 
				
			||||||
 | 
						SR_CONF_OFFSET,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** The device supports setting a pattern for the logic trigger. */
 | 
				
			||||||
 | 
						SR_CONF_TRIGGER_PATTERN,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** High resolution mode. */
 | 
				
			||||||
 | 
						SR_CONF_HIGH_RESOLUTION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Peak detection. */
 | 
				
			||||||
 | 
						SR_CONF_PEAK_DETECTION,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Logic threshold: predefined levels (TTL, ECL, CMOS, etc). */
 | 
				
			||||||
 | 
						SR_CONF_LOGIC_THRESHOLD,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Logic threshold: custom numerical value. */
 | 
				
			||||||
 | 
						SR_CONF_LOGIC_THRESHOLD_CUSTOM,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** The measurement range of a DMM or the output range of a power supply. */
 | 
				
			||||||
 | 
						SR_CONF_RANGE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** The number of digits (e.g. for a DMM). */
 | 
				
			||||||
 | 
						SR_CONF_DIGITS,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Phase of a source signal. */
 | 
				
			||||||
 | 
						SR_CONF_PHASE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/** Duty cycle of a source signal. */
 | 
				
			||||||
 | 
						SR_CONF_DUTY_CYCLE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Current power.
 | 
				
			||||||
 | 
						 * @arg type: double
 | 
				
			||||||
 | 
						 * @arg get: get measured power
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_POWER,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Power target.
 | 
				
			||||||
 | 
						 * @arg type: double
 | 
				
			||||||
 | 
						 * @arg get: get power target
 | 
				
			||||||
 | 
						 * @arg set: change power target
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_POWER_TARGET,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Resistance target.
 | 
				
			||||||
 | 
						 * @arg type: double
 | 
				
			||||||
 | 
						 * @arg get: get resistance target
 | 
				
			||||||
 | 
						 * @arg set: change resistance target
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						SR_CONF_RESISTANCE_TARGET,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
						/* Update sr_key_info_config[] (hwdriver.c) upon changes! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*--- Special stuff -------------------------------------------------*/
 | 
						/*--- Special stuff -------------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,14 @@ SR_API GSList *sr_buildinfo_libs_get(void);
 | 
				
			||||||
SR_API char *sr_buildinfo_host_get(void);
 | 
					SR_API char *sr_buildinfo_host_get(void);
 | 
				
			||||||
SR_API char *sr_buildinfo_scpi_backends_get(void);
 | 
					SR_API char *sr_buildinfo_scpi_backends_get(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*--- conversion.c ----------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_API int sr_a2l_threshold(const struct sr_datafeed_analog *analog,
 | 
				
			||||||
 | 
							float threshold, uint8_t *output, uint64_t count);
 | 
				
			||||||
 | 
					SR_API int sr_a2l_schmitt_trigger(const struct sr_datafeed_analog *analog,
 | 
				
			||||||
 | 
							float lo_thr, float hi_thr, uint8_t *state, uint8_t *output,
 | 
				
			||||||
 | 
							uint64_t count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*--- log.c -----------------------------------------------------------------*/
 | 
					/*--- log.c -----------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*sr_log_callback)(void *cb_data, int loglevel,
 | 
					typedef int (*sr_log_callback)(void *cb_data, int loglevel,
 | 
				
			||||||
| 
						 | 
					@ -59,6 +67,7 @@ SR_API int sr_log_loglevel_set(int loglevel);
 | 
				
			||||||
SR_API int sr_log_loglevel_get(void);
 | 
					SR_API int sr_log_loglevel_get(void);
 | 
				
			||||||
SR_API int sr_log_callback_set(sr_log_callback cb, void *cb_data);
 | 
					SR_API int sr_log_callback_set(sr_log_callback cb, void *cb_data);
 | 
				
			||||||
SR_API int sr_log_callback_set_default(void);
 | 
					SR_API int sr_log_callback_set_default(void);
 | 
				
			||||||
 | 
					SR_API int sr_log_callback_get(sr_log_callback *cb, void **cb_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*--- device.c --------------------------------------------------------------*/
 | 
					/*--- device.c --------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +154,10 @@ SR_API int sr_session_is_running(struct sr_session *session);
 | 
				
			||||||
SR_API int sr_session_stopped_callback_set(struct sr_session *session,
 | 
					SR_API int sr_session_stopped_callback_set(struct sr_session *session,
 | 
				
			||||||
		sr_session_stopped_callback cb, void *cb_data);
 | 
							sr_session_stopped_callback cb, void *cb_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_API int sr_packet_copy(const struct sr_datafeed_packet *packet,
 | 
				
			||||||
 | 
							struct sr_datafeed_packet **copy);
 | 
				
			||||||
 | 
					SR_API void sr_packet_free(struct sr_datafeed_packet *packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*--- input/input.c ---------------------------------------------------------*/
 | 
					/*--- input/input.c ---------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_API const struct sr_input_module **sr_input_list(void);
 | 
					SR_API const struct sr_input_module **sr_input_list(void);
 | 
				
			||||||
| 
						 | 
					@ -155,13 +168,12 @@ SR_API const char *const *sr_input_extensions_get(
 | 
				
			||||||
		const struct sr_input_module *imod);
 | 
							const struct sr_input_module *imod);
 | 
				
			||||||
SR_API const struct sr_input_module *sr_input_find(char *id);
 | 
					SR_API const struct sr_input_module *sr_input_find(char *id);
 | 
				
			||||||
SR_API const struct sr_option **sr_input_options_get(const struct sr_input_module *imod);
 | 
					SR_API const struct sr_option **sr_input_options_get(const struct sr_input_module *imod);
 | 
				
			||||||
SR_API gboolean sr_output_test_flag(const struct sr_output_module *omod,
 | 
					 | 
				
			||||||
		uint64_t flag);
 | 
					 | 
				
			||||||
SR_API void sr_input_options_free(const struct sr_option **options);
 | 
					SR_API void sr_input_options_free(const struct sr_option **options);
 | 
				
			||||||
SR_API struct sr_input *sr_input_new(const struct sr_input_module *imod,
 | 
					SR_API struct sr_input *sr_input_new(const struct sr_input_module *imod,
 | 
				
			||||||
		GHashTable *options);
 | 
							GHashTable *options);
 | 
				
			||||||
SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in);
 | 
					SR_API int sr_input_scan_buffer(GString *buf, const struct sr_input **in);
 | 
				
			||||||
SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in);
 | 
					SR_API int sr_input_scan_file(const char *filename, const struct sr_input **in);
 | 
				
			||||||
 | 
					SR_API const struct sr_input_module *sr_input_module_get(const struct sr_input *in);
 | 
				
			||||||
SR_API struct sr_dev_inst *sr_input_dev_inst_get(const struct sr_input *in);
 | 
					SR_API struct sr_dev_inst *sr_input_dev_inst_get(const struct sr_input *in);
 | 
				
			||||||
SR_API int sr_input_send(const struct sr_input *in, GString *buf);
 | 
					SR_API int sr_input_send(const struct sr_input *in, GString *buf);
 | 
				
			||||||
SR_API int sr_input_end(const struct sr_input *in);
 | 
					SR_API int sr_input_end(const struct sr_input *in);
 | 
				
			||||||
| 
						 | 
					@ -182,6 +194,8 @@ SR_API void sr_output_options_free(const struct sr_option **opts);
 | 
				
			||||||
SR_API const struct sr_output *sr_output_new(const struct sr_output_module *omod,
 | 
					SR_API const struct sr_output *sr_output_new(const struct sr_output_module *omod,
 | 
				
			||||||
		GHashTable *params, const struct sr_dev_inst *sdi,
 | 
							GHashTable *params, const struct sr_dev_inst *sdi,
 | 
				
			||||||
		const char *filename);
 | 
							const char *filename);
 | 
				
			||||||
 | 
					SR_API gboolean sr_output_test_flag(const struct sr_output_module *omod,
 | 
				
			||||||
 | 
							uint64_t flag);
 | 
				
			||||||
SR_API int sr_output_send(const struct sr_output *o,
 | 
					SR_API int sr_output_send(const struct sr_output *o,
 | 
				
			||||||
		const struct sr_datafeed_packet *packet, GString **out);
 | 
							const struct sr_datafeed_packet *packet, GString **out);
 | 
				
			||||||
SR_API int sr_output_free(const struct sr_output *o);
 | 
					SR_API int sr_output_free(const struct sr_output *o);
 | 
				
			||||||
| 
						 | 
					@ -221,6 +235,8 @@ typedef int (*sr_resource_close_callback)(struct sr_resource *res,
 | 
				
			||||||
typedef gssize (*sr_resource_read_callback)(const struct sr_resource *res,
 | 
					typedef gssize (*sr_resource_read_callback)(const struct sr_resource *res,
 | 
				
			||||||
		void *buf, size_t count, void *cb_data);
 | 
							void *buf, size_t count, void *cb_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_API GSList *sr_resourcepaths_get(int res_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_API int sr_resource_set_hooks(struct sr_context *ctx,
 | 
					SR_API int sr_resource_set_hooks(struct sr_context *ctx,
 | 
				
			||||||
		sr_resource_open_callback open_cb,
 | 
							sr_resource_open_callback open_cb,
 | 
				
			||||||
		sr_resource_close_callback close_cb,
 | 
							sr_resource_close_callback close_cb,
 | 
				
			||||||
| 
						 | 
					@ -237,6 +253,12 @@ SR_API uint64_t sr_parse_timestring(const char *timestring);
 | 
				
			||||||
SR_API gboolean sr_parse_boolstring(const char *boolstring);
 | 
					SR_API gboolean sr_parse_boolstring(const char *boolstring);
 | 
				
			||||||
SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q);
 | 
					SR_API int sr_parse_period(const char *periodstr, uint64_t *p, uint64_t *q);
 | 
				
			||||||
SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q);
 | 
					SR_API int sr_parse_voltage(const char *voltstr, uint64_t *p, uint64_t *q);
 | 
				
			||||||
 | 
					SR_API int sr_sprintf_ascii(char *buf, const char *format, ...);
 | 
				
			||||||
 | 
					SR_API int sr_vsprintf_ascii(char *buf, const char *format, va_list args);
 | 
				
			||||||
 | 
					SR_API int sr_snprintf_ascii(char *buf, size_t buf_size,
 | 
				
			||||||
 | 
							const char *format, ...);
 | 
				
			||||||
 | 
					SR_API int sr_vsnprintf_ascii(char *buf, size_t buf_size,
 | 
				
			||||||
 | 
							const char *format, va_list args);
 | 
				
			||||||
SR_API int sr_parse_rational(const char *str, struct sr_rational *ret);
 | 
					SR_API int sr_parse_rational(const char *str, struct sr_rational *ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*--- version.c -------------------------------------------------------------*/
 | 
					/*--- version.c -------------------------------------------------------------*/
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ libdir=@libdir@
 | 
				
			||||||
includedir=@includedir@
 | 
					includedir=@includedir@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Name: libsigrok
 | 
					Name: libsigrok
 | 
				
			||||||
Description: Backend library of the sigrok logic analyzer software
 | 
					Description: Backend library for the sigrok signal analysis software suite
 | 
				
			||||||
URL: http://www.sigrok.org
 | 
					URL: http://www.sigrok.org
 | 
				
			||||||
Requires: glib-2.0
 | 
					Requires: glib-2.0
 | 
				
			||||||
Requires.private: @SR_PKGLIBS@
 | 
					Requires.private: @SR_PKGLIBS@
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										293
									
								
								src/analog.c
								
								
								
								
							
							
						
						
									
										293
									
								
								src/analog.c
								
								
								
								
							| 
						 | 
					@ -88,6 +88,9 @@ static struct unit_mq_string unit_strings[] = {
 | 
				
			||||||
	{ SR_UNIT_MOMME, "momme" },
 | 
						{ SR_UNIT_MOMME, "momme" },
 | 
				
			||||||
	{ SR_UNIT_TOLA, "tola" },
 | 
						{ SR_UNIT_TOLA, "tola" },
 | 
				
			||||||
	{ SR_UNIT_PIECE, "pcs" },
 | 
						{ SR_UNIT_PIECE, "pcs" },
 | 
				
			||||||
 | 
						{ SR_UNIT_JOULE, "J" },
 | 
				
			||||||
 | 
						{ SR_UNIT_COULOMB, "C" },
 | 
				
			||||||
 | 
						{ SR_UNIT_AMPERE_HOUR, "Ah" },
 | 
				
			||||||
	ALL_ZERO
 | 
						ALL_ZERO
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,8 +160,8 @@ SR_PRIV int sr_analog_init(struct sr_datafeed_analog *analog,
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Convert an analog datafeed payload to an array of floats.
 | 
					 * Convert an analog datafeed payload to an array of floats.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Sufficient memory for outbuf must have been pre-allocated by the caller,
 | 
					 * The caller must provide the #outbuf space for the conversion result,
 | 
				
			||||||
 * who is also responsible for freeing it when no longer needed.
 | 
					 * and is expected to free allocated space after use.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param[in] analog The analog payload to convert. Must not be NULL.
 | 
					 * @param[in] analog The analog payload to convert. Must not be NULL.
 | 
				
			||||||
 *                   analog->data, analog->meaning, and analog->encoding
 | 
					 *                   analog->data, analog->meaning, and analog->encoding
 | 
				
			||||||
| 
						 | 
					@ -174,126 +177,206 @@ SR_PRIV int sr_analog_init(struct sr_datafeed_analog *analog,
 | 
				
			||||||
SR_API int sr_analog_to_float(const struct sr_datafeed_analog *analog,
 | 
					SR_API int sr_analog_to_float(const struct sr_datafeed_analog *analog,
 | 
				
			||||||
		float *outbuf)
 | 
							float *outbuf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	float offset;
 | 
						size_t count;
 | 
				
			||||||
	unsigned int b, i, count;
 | 
						gboolean host_bigendian;
 | 
				
			||||||
	gboolean bigendian;
 | 
						gboolean input_float, input_signed, input_bigendian;
 | 
				
			||||||
 | 
						size_t input_unitsize;
 | 
				
			||||||
 | 
						double scale, offset, value;
 | 
				
			||||||
 | 
						const uint8_t *data8;
 | 
				
			||||||
 | 
						gboolean input_is_native;
 | 
				
			||||||
 | 
						char type_text[10];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!analog || !(analog->data) || !(analog->meaning)
 | 
						if (!analog || !analog->data || !analog->meaning || !analog->encoding)
 | 
				
			||||||
			|| !(analog->encoding) || !outbuf)
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						if (!outbuf)
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = analog->num_samples * g_slist_length(analog->meaning->channels);
 | 
						count = analog->num_samples * g_slist_length(analog->meaning->channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Determine properties of the input data's and the host's
 | 
				
			||||||
 | 
						 * native formats, to simplify test conditions below.
 | 
				
			||||||
 | 
						 * Error messages for unsupported input property combinations
 | 
				
			||||||
 | 
						 * will only be seen by developers and maintainers of input
 | 
				
			||||||
 | 
						 * formats or acquisition device drivers. Terse output is
 | 
				
			||||||
 | 
						 * acceptable there, users shall never see them.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
#ifdef WORDS_BIGENDIAN
 | 
					#ifdef WORDS_BIGENDIAN
 | 
				
			||||||
	bigendian = TRUE;
 | 
						host_bigendian = TRUE;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	bigendian = FALSE;
 | 
						host_bigendian = FALSE;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						input_float = analog->encoding->is_float;
 | 
				
			||||||
 | 
						input_signed = analog->encoding->is_signed;
 | 
				
			||||||
 | 
						input_bigendian = analog->encoding->is_bigendian;
 | 
				
			||||||
 | 
						input_unitsize = analog->encoding->unitsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!analog->encoding->is_float) {
 | 
						/*
 | 
				
			||||||
		float offset = analog->encoding->offset.p / (float)analog->encoding->offset.q;
 | 
						 * Prepare the iteration over the sample data: Get the common
 | 
				
			||||||
		float scale = analog->encoding->scale.p / (float)analog->encoding->scale.q;
 | 
						 * scale/offset factors which apply to all individual values.
 | 
				
			||||||
		gboolean is_signed = analog->encoding->is_signed;
 | 
						 * Position the read pointer on the first byte of input data.
 | 
				
			||||||
		gboolean is_bigendian = analog->encoding->is_bigendian;
 | 
						 */
 | 
				
			||||||
		int8_t *data8 = (int8_t *)(analog->data);
 | 
						offset = analog->encoding->offset.p;
 | 
				
			||||||
		int16_t *data16 = (int16_t *)(analog->data);
 | 
						offset /= analog->encoding->offset.q;
 | 
				
			||||||
		int32_t *data32 = (int32_t *)(analog->data);
 | 
						scale = analog->encoding->scale.p;
 | 
				
			||||||
 | 
						scale /= analog->encoding->scale.q;
 | 
				
			||||||
 | 
						data8 = analog->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (analog->encoding->unitsize) {
 | 
						/*
 | 
				
			||||||
		case 1:
 | 
						 * Immediately handle the special case where input data needs
 | 
				
			||||||
			if (is_signed) {
 | 
						 * no conversion because it already is in the application's
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
						 * native format. Do apply scale/offset though when applicable
 | 
				
			||||||
					outbuf[i] = scale * data8[i];
 | 
						 * on our way out.
 | 
				
			||||||
					outbuf[i] += offset;
 | 
						 */
 | 
				
			||||||
				}
 | 
						input_is_native = input_float &&
 | 
				
			||||||
			} else {
 | 
							input_unitsize == sizeof(outbuf[0]) &&
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
							input_bigendian == host_bigendian;
 | 
				
			||||||
					outbuf[i] = scale * R8(data8 + i);
 | 
						if (input_is_native) {
 | 
				
			||||||
					outbuf[i] += offset;
 | 
							memcpy(outbuf, data8, count * sizeof(outbuf[0]));
 | 
				
			||||||
 | 
							if (scale != 1.0 || offset != 0.0) {
 | 
				
			||||||
 | 
								while (count--) {
 | 
				
			||||||
 | 
									*outbuf *= scale;
 | 
				
			||||||
 | 
									*outbuf += offset;
 | 
				
			||||||
 | 
									outbuf++;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			break;
 | 
							return SR_OK;
 | 
				
			||||||
		case 2:
 | 
					 | 
				
			||||||
			if (is_signed && is_bigendian) {
 | 
					 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
					outbuf[i] = scale * RB16S(&data16[i]);
 | 
					 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			} else if (is_bigendian) {
 | 
					
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
						/*
 | 
				
			||||||
					outbuf[i] = scale * RB16(&data16[i]);
 | 
						 * Accept sample values in different widths and data types and
 | 
				
			||||||
					outbuf[i] += offset;
 | 
						 * endianess formats (floating point or signed or unsigned
 | 
				
			||||||
 | 
						 * integer, in either endianess, for a set of supported widths).
 | 
				
			||||||
 | 
						 * Common scale/offset factors apply to all sample values.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Do most internal calculations on double precision values.
 | 
				
			||||||
 | 
						 * Only trim the result data to single precision, since that's
 | 
				
			||||||
 | 
						 * the routine's result data type in its public API which needs
 | 
				
			||||||
 | 
						 * to be kept for compatibility. It remains an option for later
 | 
				
			||||||
 | 
						 * to add another public routine which returns double precision
 | 
				
			||||||
 | 
						 * result data, call sites could migrate at their own pace.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (input_float && input_unitsize == sizeof(float)) {
 | 
				
			||||||
 | 
							float (*reader)(const uint8_t **p);
 | 
				
			||||||
 | 
							if (input_bigendian)
 | 
				
			||||||
 | 
								reader = read_fltbe_inc;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								reader = read_fltle_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			} else if (is_signed) {
 | 
							return SR_OK;
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
					outbuf[i] = scale * RL16S(&data16[i]);
 | 
					 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			} else {
 | 
						if (input_float && input_unitsize == sizeof(double)) {
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
							double (*reader)(const uint8_t **p);
 | 
				
			||||||
					outbuf[i] = scale * RL16(&data16[i]);
 | 
							if (input_bigendian)
 | 
				
			||||||
					outbuf[i] += offset;
 | 
								reader = read_dblbe_inc;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								reader = read_dblle_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			break;
 | 
						if (input_float) {
 | 
				
			||||||
		case 4:
 | 
							snprintf(type_text, sizeof(type_text), "%c%zu%s",
 | 
				
			||||||
			if (is_signed && is_bigendian) {
 | 
								'f', input_unitsize * 8, input_bigendian ? "be" : "le");
 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
							sr_err("Unsupported type for analog-to-float conversion: %s.",
 | 
				
			||||||
					outbuf[i] = scale * RB32S(&data32[i]);
 | 
								type_text);
 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else if (is_bigendian) {
 | 
					 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
					outbuf[i] = scale * RB32(&data32[i]);
 | 
					 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else if (is_signed) {
 | 
					 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
					outbuf[i] = scale * RL32S(&data32[i]);
 | 
					 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				for (unsigned int i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
					outbuf[i] = scale * RL32(&data32[i]);
 | 
					 | 
				
			||||||
					outbuf[i] += offset;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			sr_err("Unsupported unit size '%d' for analog-to-float"
 | 
					 | 
				
			||||||
			       " conversion.", analog->encoding->unitsize);
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (input_unitsize == sizeof(uint8_t) && input_signed) {
 | 
				
			||||||
 | 
							int8_t (*reader)(const uint8_t **p);
 | 
				
			||||||
 | 
							reader = read_i8_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return SR_OK;
 | 
							return SR_OK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (input_unitsize == sizeof(uint8_t)) {
 | 
				
			||||||
	if (analog->encoding->unitsize == sizeof(float)
 | 
							uint8_t (*reader)(const uint8_t **p);
 | 
				
			||||||
			&& analog->encoding->is_bigendian == bigendian
 | 
							reader = read_u8_inc;
 | 
				
			||||||
			&& analog->encoding->scale.p == 1
 | 
							while (count--) {
 | 
				
			||||||
			&& analog->encoding->scale.q == 1
 | 
								value = reader(&data8);
 | 
				
			||||||
			&& analog->encoding->offset.p / (float)analog->encoding->offset.q == 0) {
 | 
								value *= scale;
 | 
				
			||||||
		/* The data is already in the right format. */
 | 
								value += offset;
 | 
				
			||||||
		memcpy(outbuf, analog->data, count * sizeof(float));
 | 
								*outbuf++ = value;
 | 
				
			||||||
	} else {
 | 
							}
 | 
				
			||||||
		for (i = 0; i < count; i += analog->encoding->unitsize) {
 | 
							return SR_OK;
 | 
				
			||||||
			for (b = 0; b < analog->encoding->unitsize; b++) {
 | 
						}
 | 
				
			||||||
				if (analog->encoding->is_bigendian == bigendian)
 | 
						if (input_unitsize == sizeof(uint16_t) && input_signed) {
 | 
				
			||||||
					((uint8_t *)outbuf)[i + b] =
 | 
							int16_t (*reader)(const uint8_t **p);
 | 
				
			||||||
						((uint8_t *)analog->data)[i * analog->encoding->unitsize + b];
 | 
							if (input_bigendian)
 | 
				
			||||||
 | 
								reader = read_i16be_inc;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
					((uint8_t *)outbuf)[i + (analog->encoding->unitsize - b)] =
 | 
								reader = read_i16le_inc;
 | 
				
			||||||
						((uint8_t *)analog->data)[i * analog->encoding->unitsize + b];
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
			if (analog->encoding->scale.p != 1
 | 
					 | 
				
			||||||
					|| analog->encoding->scale.q != 1)
 | 
					 | 
				
			||||||
				outbuf[i] = (outbuf[i] * analog->encoding->scale.p) / analog->encoding->scale.q;
 | 
					 | 
				
			||||||
			offset = ((float)analog->encoding->offset.p / (float)analog->encoding->offset.q);
 | 
					 | 
				
			||||||
			outbuf[i] += offset;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
							return SR_OK;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (input_unitsize == sizeof(uint16_t)) {
 | 
				
			||||||
 | 
							uint16_t (*reader)(const uint8_t **p);
 | 
				
			||||||
 | 
							if (input_bigendian)
 | 
				
			||||||
 | 
								reader = read_u16be_inc;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								reader = read_u16le_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (input_unitsize == sizeof(uint32_t) && input_signed) {
 | 
				
			||||||
 | 
							int32_t (*reader)(const uint8_t **p);
 | 
				
			||||||
 | 
							if (input_bigendian)
 | 
				
			||||||
 | 
								reader = read_i32be_inc;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								reader = read_i32le_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (input_unitsize == sizeof(uint32_t)) {
 | 
				
			||||||
 | 
							uint32_t (*reader)(const uint8_t **p);
 | 
				
			||||||
 | 
							if (input_bigendian)
 | 
				
			||||||
 | 
								reader = read_u32be_inc;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								reader = read_u32le_inc;
 | 
				
			||||||
 | 
							while (count--) {
 | 
				
			||||||
 | 
								value = reader(&data8);
 | 
				
			||||||
 | 
								value *= scale;
 | 
				
			||||||
 | 
								value += offset;
 | 
				
			||||||
 | 
								*outbuf++ = value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						snprintf(type_text, sizeof(type_text), "%c%zu%s",
 | 
				
			||||||
 | 
							input_float ? 'f' : input_signed ? 'i' : 'u',
 | 
				
			||||||
 | 
							input_unitsize * 8, input_bigendian ? "be" : "le");
 | 
				
			||||||
 | 
						sr_err("Unsupported type for analog-to-float conversion: %s.",
 | 
				
			||||||
 | 
							type_text);
 | 
				
			||||||
 | 
						return SR_ERR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Scale a float value to the appropriate SI prefix.
 | 
					 * Scale a float value to the appropriate SI prefix.
 | 
				
			||||||
| 
						 | 
					@ -366,12 +449,9 @@ SR_API gboolean sr_analog_si_prefix_friendly(enum sr_unit unit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(prefix_friendly_units); i++)
 | 
						for (i = 0; i < ARRAY_SIZE(prefix_friendly_units); i++)
 | 
				
			||||||
		if (unit == prefix_friendly_units[i])
 | 
							if (unit == prefix_friendly_units[i])
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (unit != prefix_friendly_units[i])
 | 
					 | 
				
			||||||
		return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return TRUE;
 | 
								return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -555,8 +635,8 @@ SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res->p = (int64_t)(p);
 | 
						res->p = (int64_t)p;
 | 
				
			||||||
	res->q = (uint64_t)(q);
 | 
						res->q = (uint64_t)q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -606,9 +686,8 @@ SR_API int sr_rational_mult(struct sr_rational *res, const struct sr_rational *a
 | 
				
			||||||
 * @param[out] res Result.
 | 
					 * @param[out] res Result.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @retval SR_OK Success.
 | 
					 * @retval SR_OK Success.
 | 
				
			||||||
 * @retval SR_ERR_ARG Division by zero.
 | 
					 * @retval SR_ERR_ARG Division by zero, denominator of divisor too large,
 | 
				
			||||||
 * @retval SR_ERR_ARG Denominator of divisor too large.
 | 
					 *                    or resulting value too large.
 | 
				
			||||||
 * @retval SR_ERR_ARG Resulting value too large.
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @since 0.5.0
 | 
					 * @since 0.5.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,8 +63,8 @@
 | 
				
			||||||
 * @section sec_irc IRC
 | 
					 * @section sec_irc IRC
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * You can find the sigrok developers in the
 | 
					 * You can find the sigrok developers in the
 | 
				
			||||||
 * <a href="irc://chat.freenode.net/sigrok">\#sigrok</a>
 | 
					 * <a href="ircs://irc.libera.chat/#sigrok">\#sigrok</a>
 | 
				
			||||||
 * IRC channel on Freenode.
 | 
					 * IRC channel on Libera.Chat.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @section sec_website Website
 | 
					 * @section sec_website Website
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -153,9 +153,25 @@ SR_API GSList *sr_buildinfo_libs_get(void)
 | 
				
			||||||
	m = g_slist_append(m, g_strdup_printf("%s", CONF_LIBUSB_1_0_VERSION));
 | 
						m = g_slist_append(m, g_strdup_printf("%s", CONF_LIBUSB_1_0_VERSION));
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	lv = libusb_get_version();
 | 
						lv = libusb_get_version();
 | 
				
			||||||
	m = g_slist_append(m, g_strdup_printf("%d.%d.%d.%d%s",
 | 
						m = g_slist_append(m, g_strdup_printf("%d.%d.%d.%d%s API 0x%08x",
 | 
				
			||||||
		lv->major, lv->minor, lv->micro, lv->nano, lv->rc));
 | 
							lv->major, lv->minor, lv->micro, lv->nano, lv->rc,
 | 
				
			||||||
 | 
					#if defined(LIBUSB_API_VERSION)
 | 
				
			||||||
 | 
							LIBUSB_API_VERSION
 | 
				
			||||||
 | 
					#elif defined(LIBUSBX_API_VERSION)
 | 
				
			||||||
 | 
							LIBUSBX_API_VERSION
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
							));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						l = g_slist_append(l, m);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef HAVE_LIBHIDAPI
 | 
				
			||||||
 | 
						m = g_slist_append(NULL, g_strdup("hidapi"));
 | 
				
			||||||
 | 
						m = g_slist_append(m, g_strdup_printf("%s", CONF_LIBHIDAPI_VERSION));
 | 
				
			||||||
 | 
						l = g_slist_append(l, m);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef HAVE_LIBBLUEZ
 | 
				
			||||||
 | 
						m = g_slist_append(NULL, g_strdup("bluez"));
 | 
				
			||||||
 | 
						m = g_slist_append(m, g_strdup_printf("%s", CONF_LIBBLUEZ_VERSION));
 | 
				
			||||||
	l = g_slist_append(l, m);
 | 
						l = g_slist_append(l, m);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_LIBFTDI
 | 
					#ifdef HAVE_LIBFTDI
 | 
				
			||||||
| 
						 | 
					@ -199,7 +215,7 @@ SR_API char *sr_buildinfo_scpi_backends_get(void)
 | 
				
			||||||
#if HAVE_RPC
 | 
					#if HAVE_RPC
 | 
				
			||||||
	g_string_append_printf(s, "RPC, ");
 | 
						g_string_append_printf(s, "RPC, ");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_LIBSERIALPORT
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
	g_string_append_printf(s, "serial, ");
 | 
						g_string_append_printf(s, "serial, ");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_LIBREVISA
 | 
					#ifdef HAVE_LIBREVISA
 | 
				
			||||||
| 
						 | 
					@ -226,8 +242,7 @@ static void print_versions(void)
 | 
				
			||||||
	char *str;
 | 
						char *str;
 | 
				
			||||||
	const char *lib, *version;
 | 
						const char *lib, *version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_dbg("libsigrok %s/%s (rt: %s/%s).",
 | 
						sr_dbg("libsigrok %s/%s.",
 | 
				
			||||||
		SR_PACKAGE_VERSION_STRING, SR_LIB_VERSION_STRING,
 | 
					 | 
				
			||||||
		sr_package_version_string_get(), sr_lib_version_string_get());
 | 
							sr_package_version_string_get(), sr_lib_version_string_get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = g_string_sized_new(200);
 | 
						s = g_string_sized_new(200);
 | 
				
			||||||
| 
						 | 
					@ -255,6 +270,17 @@ static void print_versions(void)
 | 
				
			||||||
	g_free(str);
 | 
						g_free(str);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void print_resourcepaths(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						GSList *l, *l_orig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("Firmware search paths:");
 | 
				
			||||||
 | 
						l_orig = sr_resourcepaths_get(SR_RESOURCE_FIRMWARE);
 | 
				
			||||||
 | 
						for (l = l_orig; l; l = l->next)
 | 
				
			||||||
 | 
							sr_dbg(" - %s", (const char *)l->data);
 | 
				
			||||||
 | 
						g_slist_free_full(l_orig, g_free);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Sanity-check all libsigrok drivers.
 | 
					 * Sanity-check all libsigrok drivers.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -309,7 +335,10 @@ static int sanity_check_all_drivers(const struct sr_context *ctx)
 | 
				
			||||||
			sr_err("No dev_list in driver %d ('%s').", i, d);
 | 
								sr_err("No dev_list in driver %d ('%s').", i, d);
 | 
				
			||||||
			errors++;
 | 
								errors++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* Note: dev_clear() is optional. */
 | 
							if (!drivers[i]->dev_clear) {
 | 
				
			||||||
 | 
								sr_err("No dev_clear in driver %d ('%s').", i, d);
 | 
				
			||||||
 | 
								errors++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		/* Note: config_get() is optional. */
 | 
							/* Note: config_get() is optional. */
 | 
				
			||||||
		if (!drivers[i]->config_set) {
 | 
							if (!drivers[i]->config_set) {
 | 
				
			||||||
			sr_err("No config_set in driver %d ('%s').", i, d);
 | 
								sr_err("No config_set in driver %d ('%s').", i, d);
 | 
				
			||||||
| 
						 | 
					@ -526,6 +555,8 @@ SR_API int sr_init(struct sr_context **ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print_versions();
 | 
						print_versions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_resourcepaths();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ctx) {
 | 
						if (!ctx) {
 | 
				
			||||||
		sr_err("%s(): libsigrok context was NULL.", __func__);
 | 
							sr_err("%s(): libsigrok context was NULL.", __func__);
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
| 
						 | 
					@ -537,22 +568,22 @@ SR_API int sr_init(struct sr_context **ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sanity_check_all_drivers(context) < 0) {
 | 
						if (sanity_check_all_drivers(context) < 0) {
 | 
				
			||||||
		sr_err("Internal driver error(s), aborting.");
 | 
							sr_err("Internal driver error(s), aborting.");
 | 
				
			||||||
		return ret;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sanity_check_all_input_modules() < 0) {
 | 
						if (sanity_check_all_input_modules() < 0) {
 | 
				
			||||||
		sr_err("Internal input module error(s), aborting.");
 | 
							sr_err("Internal input module error(s), aborting.");
 | 
				
			||||||
		return ret;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sanity_check_all_output_modules() < 0) {
 | 
						if (sanity_check_all_output_modules() < 0) {
 | 
				
			||||||
		sr_err("Internal output module error(s), aborting.");
 | 
							sr_err("Internal output module error(s), aborting.");
 | 
				
			||||||
		return ret;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sanity_check_all_transform_modules() < 0) {
 | 
						if (sanity_check_all_transform_modules() < 0) {
 | 
				
			||||||
		sr_err("Internal transform module error(s), aborting.");
 | 
							sr_err("Internal transform module error(s), aborting.");
 | 
				
			||||||
		return ret;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
| 
						 | 
					@ -570,6 +601,20 @@ SR_API int sr_init(struct sr_context **ctx)
 | 
				
			||||||
		ret = SR_ERR;
 | 
							ret = SR_ERR;
 | 
				
			||||||
		goto done;
 | 
							goto done;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef HAVE_LIBHIDAPI
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * According to <hidapi.h>, the hid_init() routine just returns
 | 
				
			||||||
 | 
						 * zero or non-zero, and hid_error() appears to relate to calls
 | 
				
			||||||
 | 
						 * for a specific device after hid_open(). Which means that there
 | 
				
			||||||
 | 
						 * is no more detailled information available beyond success/fail
 | 
				
			||||||
 | 
						 * at this point in time.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (hid_init() != 0) {
 | 
				
			||||||
 | 
							sr_err("HIDAPI hid_init() failed.");
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
							goto done;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	sr_resource_set_hooks(context, NULL, NULL, NULL, NULL);
 | 
						sr_resource_set_hooks(context, NULL, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -577,9 +622,7 @@ SR_API int sr_init(struct sr_context **ctx)
 | 
				
			||||||
	context = NULL;
 | 
						context = NULL;
 | 
				
			||||||
	ret = SR_OK;
 | 
						ret = SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(HAVE_LIBUSB_1_0) || defined(_WIN32)
 | 
					 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	g_free(context);
 | 
						g_free(context);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -607,6 +650,9 @@ SR_API int sr_exit(struct sr_context *ctx)
 | 
				
			||||||
	WSACleanup();
 | 
						WSACleanup();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_LIBHIDAPI
 | 
				
			||||||
 | 
						hid_exit();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef HAVE_LIBUSB_1_0
 | 
					#ifdef HAVE_LIBUSB_1_0
 | 
				
			||||||
	libusb_exit(ctx->libusb_ctx);
 | 
						libusb_exit(ctx->libusb_ctx);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,105 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Andreas Sandberg <andreas@sandberg.pp.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int bv_get_value(float *out, const struct binary_value_spec *spec, const void *data, size_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						float value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!out || !spec || !data)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VALUE_TYPE(T, R, L)				\
 | 
				
			||||||
 | 
						case T:						\
 | 
				
			||||||
 | 
							if (spec->offset + (L) > length)	\
 | 
				
			||||||
 | 
								return SR_ERR_DATA;		\
 | 
				
			||||||
 | 
							value = R(data + spec->offset);		\
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (spec->type) {
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_UINT8, R8, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_BE_UINT16, RB16, 2);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_BE_UINT32, RB32, 4);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_BE_UINT64, RB64, 8);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_BE_FLOAT, RBFL, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_LE_UINT16, RL16, 2);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_LE_UINT32, RL32, 4);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_LE_UINT64, RL64, 8);
 | 
				
			||||||
 | 
							VALUE_TYPE(BVT_LE_FLOAT, RLFL, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef VALUE_TYPE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*out = value * spec->scale;
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int bv_send_analog_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch,
 | 
				
			||||||
 | 
									   const struct binary_analog_channel *bac, const void *data, size_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct sr_analog_encoding encoding;
 | 
				
			||||||
 | 
						struct sr_analog_meaning meaning;
 | 
				
			||||||
 | 
						struct sr_analog_spec spec;
 | 
				
			||||||
 | 
						struct sr_datafeed_analog analog;
 | 
				
			||||||
 | 
						struct sr_datafeed_packet packet = {
 | 
				
			||||||
 | 
							.type = SR_DF_ANALOG,
 | 
				
			||||||
 | 
							.payload = &analog,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						float value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = bv_get_value(&value, &bac->spec, data, length);
 | 
				
			||||||
 | 
						if (err != SR_OK)
 | 
				
			||||||
 | 
							goto err_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sr_analog_init(&analog, &encoding, &meaning, &spec, bac->digits);
 | 
				
			||||||
 | 
						if (err != SR_OK)
 | 
				
			||||||
 | 
							goto err_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						meaning.mq = bac->mq;
 | 
				
			||||||
 | 
						meaning.unit = bac->unit;
 | 
				
			||||||
 | 
						meaning.mqflags = 0;
 | 
				
			||||||
 | 
						meaning.channels = g_slist_append(NULL, ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spec.spec_digits = bac->digits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						analog.data = &value;
 | 
				
			||||||
 | 
						analog.num_samples = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = sr_session_send(sdi, &packet);
 | 
				
			||||||
 | 
						if (err != SR_OK)
 | 
				
			||||||
 | 
							goto err_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_free:
 | 
				
			||||||
 | 
						g_slist_free(meaning.channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_out:
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,109 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2017 Soeren Apel <soeren@apelpie.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Conversion helper functions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @cond PRIVATE */
 | 
				
			||||||
 | 
					#define LOG_PREFIX "conv"
 | 
				
			||||||
 | 
					/** @endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert analog values to logic values by using a fixed threshold.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] analog The analog input values.
 | 
				
			||||||
 | 
					 * @param[in] threshold The threshold to use.
 | 
				
			||||||
 | 
					 * @param[out] output The converted output values; either 0 or 1. Must provide
 | 
				
			||||||
 | 
					 *                    space for count bytes.
 | 
				
			||||||
 | 
					 * @param[in] count The number of samples to process.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return SR_OK on success or SR_ERR on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_API int sr_a2l_threshold(const struct sr_datafeed_analog *analog,
 | 
				
			||||||
 | 
							float threshold, uint8_t *output, uint64_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						float *input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!analog->encoding->is_float) {
 | 
				
			||||||
 | 
							input = g_try_malloc(sizeof(float) * count);
 | 
				
			||||||
 | 
							if (!input)
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sr_analog_to_float(analog, input);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							input = analog->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (uint64_t i = 0; i < count; i++)
 | 
				
			||||||
 | 
							output[i] = (input[i] >= threshold) ? 1 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!analog->encoding->is_float)
 | 
				
			||||||
 | 
							g_free(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert analog values to logic values by using a Schmitt-trigger algorithm.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param analog The analog input values.
 | 
				
			||||||
 | 
					 * @param lo_thr The low threshold - result becomes 0 below it.
 | 
				
			||||||
 | 
					 * @param hi_thr The high threshold - result becomes 1 above it.
 | 
				
			||||||
 | 
					 * @param state The internal converter state. Must contain the state of logic
 | 
				
			||||||
 | 
					 *        sample n-1, will contain the state of logic sample n+count upon exit.
 | 
				
			||||||
 | 
					 * @param output The converted output values; either 0 or 1. Must provide
 | 
				
			||||||
 | 
					 *        space for count bytes.
 | 
				
			||||||
 | 
					 * @param count The number of samples to process.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return SR_OK on success or SR_ERR on failure.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_API int sr_a2l_schmitt_trigger(const struct sr_datafeed_analog *analog,
 | 
				
			||||||
 | 
							float lo_thr, float hi_thr, uint8_t *state, uint8_t *output,
 | 
				
			||||||
 | 
							uint64_t count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						float *input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!analog->encoding->is_float) {
 | 
				
			||||||
 | 
							input = g_try_malloc(sizeof(float) * count);
 | 
				
			||||||
 | 
							if (!input)
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sr_analog_to_float(analog, input);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							input = analog->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (uint64_t i = 0; i < count; i++) {
 | 
				
			||||||
 | 
							if (input[i] < lo_thr)
 | 
				
			||||||
 | 
								*state = 0;
 | 
				
			||||||
 | 
							else if (input[i] > hi_thr)
 | 
				
			||||||
 | 
								*state = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							output[i] = *state;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!analog->encoding->is_float)
 | 
				
			||||||
 | 
							g_free(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
 | 
					 * Copyright (C) 2015 Aurelien Jacobs <aurel@gnuage.org>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -17,22 +17,27 @@
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef LIBSIGROK_HARDWARE_VICTOR_DMM_PROTOCOL_H
 | 
					#include <config.h>
 | 
				
			||||||
#define LIBSIGROK_HARDWARE_VICTOR_DMM_PROTOCOL_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOG_PREFIX "victor-dmm"
 | 
					SR_PRIV uint16_t sr_crc16(uint16_t crc, const uint8_t *buffer, int len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DMM_DATA_SIZE 14
 | 
						if (!buffer || len < 0)
 | 
				
			||||||
 | 
							return crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
						while (len--) {
 | 
				
			||||||
struct dev_context {
 | 
							crc ^= *buffer++;
 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
							for (i = 0; i < 8; i++) {
 | 
				
			||||||
};
 | 
								int carry = crc & 1;
 | 
				
			||||||
 | 
								crc >>= 1;
 | 
				
			||||||
 | 
								if (carry)
 | 
				
			||||||
 | 
									crc ^= 0xA001;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int victor_dmm_receive_data(struct sr_dev_inst *sdi, unsigned char *buf);
 | 
						return crc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
							
								
								
									
										228
									
								
								src/device.c
								
								
								
								
							
							
						
						
									
										228
									
								
								src/device.c
								
								
								
								
							| 
						 | 
					@ -18,10 +18,12 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					#include "scpi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @cond PRIVATE */
 | 
					/** @cond PRIVATE */
 | 
				
			||||||
#define LOG_PREFIX "device"
 | 
					#define LOG_PREFIX "device"
 | 
				
			||||||
| 
						 | 
					@ -60,7 +62,7 @@ SR_PRIV struct sr_channel *sr_channel_new(struct sr_dev_inst *sdi,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_channel *ch;
 | 
						struct sr_channel *ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ch = g_malloc0(sizeof(struct sr_channel));
 | 
						ch = g_malloc0(sizeof(*ch));
 | 
				
			||||||
	ch->sdi = sdi;
 | 
						ch->sdi = sdi;
 | 
				
			||||||
	ch->index = index;
 | 
						ch->index = index;
 | 
				
			||||||
	ch->type = type;
 | 
						ch->type = type;
 | 
				
			||||||
| 
						 | 
					@ -73,6 +75,32 @@ SR_PRIV struct sr_channel *sr_channel_new(struct sr_dev_inst *sdi,
 | 
				
			||||||
	return ch;
 | 
						return ch;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Release a previously allocated struct sr_channel.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] ch Pointer to struct sr_channel.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV void sr_channel_free(struct sr_channel *ch)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ch)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						g_free(ch->name);
 | 
				
			||||||
 | 
						g_free(ch->priv);
 | 
				
			||||||
 | 
						g_free(ch);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Wrapper around sr_channel_free(), suitable for glib iterators.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV void sr_channel_free_cb(void *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sr_channel_free(p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Set the name of the specified channel.
 | 
					 * Set the name of the specified channel.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -135,10 +163,18 @@ SR_API int sr_dev_channel_enable(struct sr_channel *channel, gboolean state)
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Returns the next enabled channel, wrapping around if necessary. */
 | 
					/**
 | 
				
			||||||
/** @private */
 | 
					 * Returns the next enabled channel, wrapping around if necessary.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] sdi The device instance the channel is connected to.
 | 
				
			||||||
 | 
					 *                Must not be NULL.
 | 
				
			||||||
 | 
					 * @param[in] cur_channel The current channel.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return A pointer to the next enabled channel of this device.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi,
 | 
				
			||||||
 | 
					 | 
				
			||||||
		struct sr_channel *cur_channel)
 | 
							struct sr_channel *cur_channel)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_channel *next_channel;
 | 
						struct sr_channel *next_channel;
 | 
				
			||||||
| 
						 | 
					@ -156,6 +192,69 @@ SR_PRIV struct sr_channel *sr_next_enabled_channel(const struct sr_dev_inst *sdi
 | 
				
			||||||
	return next_channel;
 | 
						return next_channel;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare two channels, return whether they differ.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The channels' names and types are checked. The enabled state is not
 | 
				
			||||||
 | 
					 * considered a condition for difference. The test is motivated by the
 | 
				
			||||||
 | 
					 * desire to detect changes in the configuration of acquisition setups
 | 
				
			||||||
 | 
					 * between re-reads of an input file.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] ch1 First channel.
 | 
				
			||||||
 | 
					 * @param[in] ch2 Second channel.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return TRUE upon differences or unexpected input, FALSE otherwise.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_channels_differ(struct sr_channel *ch1, struct sr_channel *ch2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!ch1 || !ch2)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ch1->type != ch2->type)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						if (strcmp(ch1->name, ch2->name))
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare two channel lists, return whether they differ.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Listing the same set of channels but in a different order is considered
 | 
				
			||||||
 | 
					 * a difference in the lists.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] l1 First channel list.
 | 
				
			||||||
 | 
					 * @param[in] l2 Second channel list.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return TRUE upon differences or unexpected input, FALSE otherwise.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_channel_lists_differ(GSList *l1, GSList *l2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sr_channel *ch1, *ch2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (l1 && l2) {
 | 
				
			||||||
 | 
							ch1 = l1->data;
 | 
				
			||||||
 | 
							ch2 = l2->data;
 | 
				
			||||||
 | 
							l1 = l1->next;
 | 
				
			||||||
 | 
							l2 = l2->next;
 | 
				
			||||||
 | 
							if (!ch1 || !ch2)
 | 
				
			||||||
 | 
								return TRUE;
 | 
				
			||||||
 | 
							if (sr_channels_differ(ch1, ch2))
 | 
				
			||||||
 | 
								return TRUE;
 | 
				
			||||||
 | 
							if (ch1->index != ch2->index)
 | 
				
			||||||
 | 
								return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (l1 || l2)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Determine whether the specified device instance has the specified
 | 
					 * Determine whether the specified device instance has the specified
 | 
				
			||||||
 * capability.
 | 
					 * capability.
 | 
				
			||||||
| 
						 | 
					@ -308,7 +407,7 @@ SR_API struct sr_dev_inst *sr_dev_inst_user_new(const char *vendor,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
						struct sr_dev_inst *sdi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
						sdi = g_malloc0(sizeof(*sdi));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi->vendor = g_strdup(vendor);
 | 
						sdi->vendor = g_strdup(vendor);
 | 
				
			||||||
	sdi->model = g_strdup(model);
 | 
						sdi->model = g_strdup(model);
 | 
				
			||||||
| 
						 | 
					@ -321,6 +420,7 @@ SR_API struct sr_dev_inst *sr_dev_inst_user_new(const char *vendor,
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Add a new channel to the specified device instance.
 | 
					 * Add a new channel to the specified device instance.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] sdi Device instance to use. Must not be NULL.
 | 
				
			||||||
 * @param[in] index @copydoc sr_channel::index
 | 
					 * @param[in] index @copydoc sr_channel::index
 | 
				
			||||||
 * @param[in] type @copydoc sr_channel::type
 | 
					 * @param[in] type @copydoc sr_channel::type
 | 
				
			||||||
 * @param[in] name @copydoc sr_channel::name
 | 
					 * @param[in] name @copydoc sr_channel::name
 | 
				
			||||||
| 
						 | 
					@ -356,9 +456,7 @@ SR_PRIV void sr_dev_inst_free(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (l = sdi->channels; l; l = l->next) {
 | 
						for (l = sdi->channels; l; l = l->next) {
 | 
				
			||||||
		ch = l->data;
 | 
							ch = l->data;
 | 
				
			||||||
		g_free(ch->name);
 | 
							sr_channel_free(ch);
 | 
				
			||||||
		g_free(ch->priv);
 | 
					 | 
				
			||||||
		g_free(ch);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	g_slist_free(sdi->channels);
 | 
						g_slist_free(sdi->channels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -400,7 +498,7 @@ SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_usb_dev_inst *udi;
 | 
						struct sr_usb_dev_inst *udi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	udi = g_malloc0(sizeof(struct sr_usb_dev_inst));
 | 
						udi = g_malloc0(sizeof(*udi));
 | 
				
			||||||
	udi->bus = bus;
 | 
						udi->bus = bus;
 | 
				
			||||||
	udi->address = address;
 | 
						udi->address = address;
 | 
				
			||||||
	udi->devhdl = hdl;
 | 
						udi->devhdl = hdl;
 | 
				
			||||||
| 
						 | 
					@ -423,7 +521,7 @@ SR_PRIV void sr_usb_dev_inst_free(struct sr_usb_dev_inst *usb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBSERIALPORT
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Allocate and init a struct for a serial device instance.
 | 
					 * Allocate and init a struct for a serial device instance.
 | 
				
			||||||
| 
						 | 
					@ -449,7 +547,7 @@ SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial = g_malloc0(sizeof(struct sr_serial_dev_inst));
 | 
						serial = g_malloc0(sizeof(*serial));
 | 
				
			||||||
	serial->port = g_strdup(port);
 | 
						serial->port = g_strdup(port);
 | 
				
			||||||
	if (serialcomm)
 | 
						if (serialcomm)
 | 
				
			||||||
		serial->serialcomm = g_strdup(serialcomm);
 | 
							serial->serialcomm = g_strdup(serialcomm);
 | 
				
			||||||
| 
						 | 
					@ -481,7 +579,7 @@ SR_PRIV struct sr_usbtmc_dev_inst *sr_usbtmc_dev_inst_new(const char *device)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sr_usbtmc_dev_inst *usbtmc;
 | 
						struct sr_usbtmc_dev_inst *usbtmc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	usbtmc = g_malloc0(sizeof(struct sr_usbtmc_dev_inst));
 | 
						usbtmc = g_malloc0(sizeof(*usbtmc));
 | 
				
			||||||
	usbtmc->device = g_strdup(device);
 | 
						usbtmc->device = g_strdup(device);
 | 
				
			||||||
	usbtmc->fd = -1;
 | 
						usbtmc->fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -529,27 +627,40 @@ SR_API GSList *sr_dev_list(const struct sr_dev_driver *driver)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SR_API int sr_dev_clear(const struct sr_dev_driver *driver)
 | 
					SR_API int sr_dev_clear(const struct sr_dev_driver *driver)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!driver) {
 | 
						if (!driver) {
 | 
				
			||||||
		sr_err("Invalid driver.");
 | 
							sr_err("Invalid driver.");
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (driver->dev_clear)
 | 
						if (!driver->context) {
 | 
				
			||||||
		ret = driver->dev_clear(driver);
 | 
							/*
 | 
				
			||||||
	else
 | 
							 * Driver was never initialized, nothing to do.
 | 
				
			||||||
		ret = std_dev_clear(driver, NULL);
 | 
							 *
 | 
				
			||||||
 | 
							 * No log message since this usually gets called for all
 | 
				
			||||||
 | 
							 * drivers, whether they were initialized or not.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						/* No log message here, too verbose and not very useful. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return driver->dev_clear(driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Open the specified device.
 | 
					 * Open the specified device instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the device instance is already open (sdi->status == SR_ST_ACTIVE),
 | 
				
			||||||
 | 
					 * SR_ERR will be returned and no re-opening of the device will be attempted.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If opening was successful, sdi->status is set to SR_ST_ACTIVE, otherwise
 | 
				
			||||||
 | 
					 * it will be left unchanged.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param sdi Device instance to use. Must not be NULL.
 | 
					 * @param sdi Device instance to use. Must not be NULL.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return SR_OK upon success, a negative error code upon errors.
 | 
					 * @retval SR_OK Success.
 | 
				
			||||||
 | 
					 * @retval SR_ERR_ARG Invalid arguments.
 | 
				
			||||||
 | 
					 * @retval SR_ERR Device instance was already active, or other error.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @since 0.2.0
 | 
					 * @since 0.2.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -558,32 +669,59 @@ SR_API int sr_dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sdi || !sdi->driver || !sdi->driver->dev_open)
 | 
						if (!sdi || !sdi->driver || !sdi->driver->dev_open)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sdi->status == SR_ST_ACTIVE) {
 | 
				
			||||||
 | 
							sr_err("%s: Device instance already active, can't re-open.",
 | 
				
			||||||
 | 
								sdi->driver->name);
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("%s: Opening device instance.", sdi->driver->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = sdi->driver->dev_open(sdi);
 | 
						ret = sdi->driver->dev_open(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret == SR_OK)
 | 
				
			||||||
 | 
							sdi->status = SR_ST_ACTIVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Close the specified device.
 | 
					 * Close the specified device instance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If the device instance is not open (sdi->status != SR_ST_ACTIVE),
 | 
				
			||||||
 | 
					 * SR_ERR_DEV_CLOSED will be returned and no closing will be attempted.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: sdi->status will be set to SR_ST_INACTIVE, regardless of whether
 | 
				
			||||||
 | 
					 * there are any errors during closing of the device instance (any errors
 | 
				
			||||||
 | 
					 * will be reported via error code and log message, though).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param sdi Device instance to use. Must not be NULL.
 | 
					 * @param sdi Device instance to use. Must not be NULL.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return SR_OK upon success, a negative error code upon errors.
 | 
					 * @retval SR_OK Success.
 | 
				
			||||||
 | 
					 * @retval SR_ERR_ARG Invalid arguments.
 | 
				
			||||||
 | 
					 * @retval SR_ERR_DEV_CLOSED Device instance was not active.
 | 
				
			||||||
 | 
					 * @retval SR_ERR Other error.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @since 0.2.0
 | 
					 * @since 0.2.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SR_API int sr_dev_close(struct sr_dev_inst *sdi)
 | 
					SR_API int sr_dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sdi || !sdi->driver || !sdi->driver->dev_close)
 | 
						if (!sdi || !sdi->driver || !sdi->driver->dev_close)
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = sdi->driver->dev_close(sdi);
 | 
						if (sdi->status != SR_ST_ACTIVE) {
 | 
				
			||||||
 | 
							sr_err("%s: Device instance not active, can't close.",
 | 
				
			||||||
 | 
								sdi->driver->name);
 | 
				
			||||||
 | 
							return SR_ERR_DEV_CLOSED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						sdi->status = SR_ST_INACTIVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("%s: Closing device instance.", sdi->driver->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sdi->driver->dev_close(sdi);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -674,19 +812,24 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi)
 | 
				
			||||||
#ifdef HAVE_LIBUSB_1_0
 | 
					#ifdef HAVE_LIBUSB_1_0
 | 
				
			||||||
	struct drv_context *drvc;
 | 
						struct drv_context *drvc;
 | 
				
			||||||
	int cnt, i, a, b;
 | 
						int cnt, i, a, b;
 | 
				
			||||||
	char connection_id[64];
 | 
						char conn_id_usb[64];
 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
						struct sr_usb_dev_inst *usb;
 | 
				
			||||||
	struct libusb_device **devlist;
 | 
						struct libusb_device **devlist;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sr_scpi_dev_inst *scpi;
 | 
				
			||||||
 | 
						char *conn_id_scpi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sdi)
 | 
						if (!sdi)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBSERIALPORT
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_SERIAL)) {
 | 
						if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_SERIAL)) {
 | 
				
			||||||
		/* connection_id isn't populated, let's do that here. */
 | 
							/* connection_id isn't populated, let's do that for serial devices. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		serial = sdi->conn;
 | 
							serial = sdi->conn;
 | 
				
			||||||
		((struct sr_dev_inst *)sdi)->connection_id = g_strdup(serial->port);
 | 
							((struct sr_dev_inst *)sdi)->connection_id = g_strdup(serial->port);
 | 
				
			||||||
| 
						 | 
					@ -695,7 +838,7 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBUSB_1_0
 | 
					#ifdef HAVE_LIBUSB_1_0
 | 
				
			||||||
	if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_USB)) {
 | 
						if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_USB)) {
 | 
				
			||||||
		/* connection_id isn't populated, let's do that here. */
 | 
							/* connection_id isn't populated, let's do that for USB devices. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		drvc = sdi->driver->context;
 | 
							drvc = sdi->driver->context;
 | 
				
			||||||
		usb = sdi->conn;
 | 
							usb = sdi->conn;
 | 
				
			||||||
| 
						 | 
					@ -713,8 +856,10 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi)
 | 
				
			||||||
			if (b != usb->bus || a != usb->address)
 | 
								if (b != usb->bus || a != usb->address)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
 | 
								if (usb_get_port_path(devlist[i], conn_id_usb, sizeof(conn_id_usb)) < 0)
 | 
				
			||||||
			((struct sr_dev_inst *)sdi)->connection_id = g_strdup(connection_id);
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								((struct sr_dev_inst *)sdi)->connection_id = g_strdup(conn_id_usb);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -722,6 +867,15 @@ SR_API const char *sr_dev_inst_connid_get(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((!sdi->connection_id) && (sdi->inst_type == SR_INST_SCPI)) {
 | 
				
			||||||
 | 
							/* connection_id isn't populated, let's do that for SCPI devices. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							scpi = sdi->conn;
 | 
				
			||||||
 | 
							sr_scpi_connection_id(scpi, &conn_id_scpi);
 | 
				
			||||||
 | 
							((struct sr_dev_inst *)sdi)->connection_id = g_strdup(conn_id_scpi);
 | 
				
			||||||
 | 
							g_free(conn_id_scpi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sdi->connection_id;
 | 
						return sdi->connection_id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,7 +379,7 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_dc)
 | 
						if (info->is_dc)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_peak_max)
 | 
						if (info->is_peak_max)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_MAX;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_MAX;
 | 
				
			||||||
	if (info->is_peak_min)
 | 
						if (info->is_peak_min)
 | 
				
			||||||
| 
						 | 
					@ -446,7 +446,7 @@ static gboolean flags_valid(const struct asycii_info *info)
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBSERIALPORT
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Arrange for the reception of another measurement from the DMM.
 | 
					 * Arrange for the reception of another measurement from the DMM.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -455,8 +455,6 @@ static gboolean flags_valid(const struct asycii_info *info)
 | 
				
			||||||
 * without the PC's intervention.
 | 
					 * without the PC's intervention.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param[in]	serial The serial connection.
 | 
					 * @param[in]	serial The serial connection.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @private
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SR_PRIV int sr_asycii_packet_request(struct sr_serial_dev_inst *serial)
 | 
					SR_PRIV int sr_asycii_packet_request(struct sr_serial_dev_inst *serial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -519,7 +517,7 @@ SR_PRIV int sr_asycii_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent;
 | 
						int ret, exponent;
 | 
				
			||||||
	struct asycii_info *info_local;
 | 
						struct asycii_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct asycii_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Don't print byte 15. That one contains the carriage return. */
 | 
						/* Don't print byte 15. That one contains the carriage return. */
 | 
				
			||||||
	sr_dbg("DMM packet: \"%.15s\"", buf);
 | 
						sr_dbg("DMM packet: \"%.15s\"", buf);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ SR_PRIV int sr_brymen_bm25x_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_VOLT;
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
		if ((analog->meaning->mqflags & (SR_MQFLAG_DC | SR_MQFLAG_AC)) == 0)
 | 
							if ((analog->meaning->mqflags & (SR_MQFLAG_DC | SR_MQFLAG_AC)) == 0)
 | 
				
			||||||
			analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
								analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (buf[14] & 2) {
 | 
						if (buf[14] & 2) {
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_CURRENT;
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,457 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
 | 
				
			||||||
 | 
					 * Copyright (C) 2019-2020 Gerhard Sittig <gerhard.sittig@gmx.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Protocol parser for Brymen BM850s DMM packets. The USB protocol (for the
 | 
				
			||||||
 | 
					 * cable) and the packet description (for the meter) were retrieved from:
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/Download2.html
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/PD02BM850s_protocolDL.html
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/images/DownloadList/ProtocolList/BM850-BM850a-BM850s_List/BM850-BM850a-BM850s-500000-count-DMM-protocol-BC85X-BC85Xa.zip
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Implementor's notes on the protocol:
 | 
				
			||||||
 | 
					 * - The BM85x devices require a low RTS pulse after COM port open and
 | 
				
			||||||
 | 
					 *   before communication of requests and responses. The vendor doc
 | 
				
			||||||
 | 
					 *   recommends 100ms pulse width including delays around it. Without
 | 
				
			||||||
 | 
					 *   that RTS pulse the meter won't respond to requests.
 | 
				
			||||||
 | 
					 * - The request has a three byte header (DLE, STX, command code), two
 | 
				
			||||||
 | 
					 *   bytes command arguments, and three bytes tail (checksum, DLE, ETX).
 | 
				
			||||||
 | 
					 *   The checksum spans the area (including) the command code and args.
 | 
				
			||||||
 | 
					 *   The checksum value is the XOR across all payload bytes. Exclusively
 | 
				
			||||||
 | 
					 *   command 0x00 is used (initiate next measurement response) which does
 | 
				
			||||||
 | 
					 *   not need arguments (passes all-zero values).
 | 
				
			||||||
 | 
					 * - The response has a four byte header (DLE, STX, command code, payload
 | 
				
			||||||
 | 
					 *   size), the respective number of payload data bytes, and a three byte
 | 
				
			||||||
 | 
					 *   tail (checksum, DLE, ETX). The checksum spans the range after the
 | 
				
			||||||
 | 
					 *   length field and before the checksum field. Command 0 response data
 | 
				
			||||||
 | 
					 *   payload consists of a four byte flags field and a text field for
 | 
				
			||||||
 | 
					 *   measurement values (floating point with exponent in ASCII).
 | 
				
			||||||
 | 
					 * - Special cases of response data:
 | 
				
			||||||
 | 
					 *   - The text field which carries the measurement value also contains
 | 
				
			||||||
 | 
					 *     whitespace which may break simple text to number conversion. Like
 | 
				
			||||||
 | 
					 *     10 02 00 0f 07 00 00 00 20 30 2e 30 30 33 32 20 45 2b 30 46 10 03
 | 
				
			||||||
 | 
					 *     which translates to: 07 00 00 00 " 0.0032 E+0". Text for overload
 | 
				
			||||||
 | 
					 *     conditions can be shorter which results in variable packet length.
 | 
				
			||||||
 | 
					 *     Some meter functions provide unexpected text for their values.
 | 
				
			||||||
 | 
					 *   - The reference impedance for decibel measurements looks wrong and
 | 
				
			||||||
 | 
					 *     requires special treatment to isolate the 4..1200R value:
 | 
				
			||||||
 | 
					 *     bfunc 80 20 00 00, text " 0. 800 E+1" (reference, 800R)
 | 
				
			||||||
 | 
					 *     The decibel measurement values use an unexpected scale.
 | 
				
			||||||
 | 
					 *     bfunc 00 20 00 00, text "-0.3702 E-1" (measurement, -37.02dBm)
 | 
				
			||||||
 | 
					 *     The reference value gets sent (sometimes) in a DMM response when
 | 
				
			||||||
 | 
					 *     the meter's function is entered, or the reference value changes.
 | 
				
			||||||
 | 
					 *     The 'bfunc' flags combination allows telling packet types apart.
 | 
				
			||||||
 | 
					 *   - Temperature measurements put the C/F unit between the mantissa
 | 
				
			||||||
 | 
					 *     and the exponent, which needs to get removed: " 0.0217CE+3"
 | 
				
			||||||
 | 
					 *   - Diode measurements appear to exclusively provide the 'Volt' flag
 | 
				
			||||||
 | 
					 *     but no 'Diode' flag. The display shows ".diod" for a moment but
 | 
				
			||||||
 | 
					 *     this information is no longer available when voltage measurements
 | 
				
			||||||
 | 
					 *     are seen.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "brymen-bm85x"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STX 0x02
 | 
				
			||||||
 | 
					#define ETX 0x03
 | 
				
			||||||
 | 
					#define DLE 0x10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CMD_GET_READING	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PKT_HEAD_LEN	4
 | 
				
			||||||
 | 
					#define PKT_DATA_MAX	15
 | 
				
			||||||
 | 
					#define PKT_TAIL_LEN	3
 | 
				
			||||||
 | 
					#define PKT_BFUNC_LEN	4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t bm85x_crc(const uint8_t *buf, size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						crc = 0;
 | 
				
			||||||
 | 
						while (len--)
 | 
				
			||||||
 | 
							crc ^= *buf++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return crc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
 | 
					/** Meter's specific activity after port open and before data exchange. */
 | 
				
			||||||
 | 
					SR_PRIV int brymen_bm85x_after_open(struct sr_serial_dev_inst *serial)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rts_toggle_delay_us;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The device requires an RTS *pulse* before communication.
 | 
				
			||||||
 | 
						 * The vendor's documentation recommends the following sequence:
 | 
				
			||||||
 | 
						 * Open the COM port, wait for 100ms, set RTS=1, wait for 100ms,
 | 
				
			||||||
 | 
						 * set RTS=0, wait for 100ms, set RTS=1, configure bitrate and
 | 
				
			||||||
 | 
						 * frame format, transmit request data, receive response data.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						rts_toggle_delay_us = 100 * 1000; /* 100ms */
 | 
				
			||||||
 | 
						g_usleep(rts_toggle_delay_us);
 | 
				
			||||||
 | 
						serial_set_handshake(serial, 1, -1);
 | 
				
			||||||
 | 
						g_usleep(rts_toggle_delay_us);
 | 
				
			||||||
 | 
						serial_set_handshake(serial, 0, -1);
 | 
				
			||||||
 | 
						g_usleep(rts_toggle_delay_us);
 | 
				
			||||||
 | 
						serial_set_handshake(serial, 1, -1);
 | 
				
			||||||
 | 
						g_usleep(rts_toggle_delay_us);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bm85x_send_command(struct sr_serial_dev_inst *serial,
 | 
				
			||||||
 | 
						uint8_t cmd, uint8_t arg1, uint8_t arg2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t buf[8];
 | 
				
			||||||
 | 
						uint8_t crc, *wrptr, *crcptr;
 | 
				
			||||||
 | 
						size_t wrlen;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wrptr = &buf[0];
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, DLE);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, STX);
 | 
				
			||||||
 | 
						crcptr = wrptr;
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, cmd);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, arg1);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, arg2);
 | 
				
			||||||
 | 
						crc = bm85x_crc(crcptr, wrptr - crcptr);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, crc);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, DLE);
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, ETX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wrlen = wrptr - &buf[0];
 | 
				
			||||||
 | 
						ret = serial_write_nonblocking(serial, &buf[0], wrlen);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if ((size_t)ret != wrlen)
 | 
				
			||||||
 | 
							return SR_ERR_IO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Initiate reception of another meter's reading. */
 | 
				
			||||||
 | 
					SR_PRIV int brymen_bm85x_packet_request(struct sr_serial_dev_inst *serial)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return bm85x_send_command(serial, CMD_GET_READING, 0, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Check Brymen BM85x DMM packet for validity.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param[in] st The DMM driver's internal state.
 | 
				
			||||||
 | 
					 * @param[in] buf The data bytes received so far.
 | 
				
			||||||
 | 
					 * @param[in] len The received data's length (byte count).
 | 
				
			||||||
 | 
					 * @param[out] pkt_len The packet's calculated total size (when valid).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The BM850s protocol uses packets of variable length. A minimum amount
 | 
				
			||||||
 | 
					 * of RX data provides the packet header, which communicates the payload
 | 
				
			||||||
 | 
					 * size, which allows to determine the packet's total size. Callers of
 | 
				
			||||||
 | 
					 * this validity checker can learn how much data will get consumed when
 | 
				
			||||||
 | 
					 * a valid packet got received and processed. The packet size is not
 | 
				
			||||||
 | 
					 * known in advance.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @returns SR_OK when the packet is valid.
 | 
				
			||||||
 | 
					 * @returns SR_ERR* (below zero) when the packet is invalid.
 | 
				
			||||||
 | 
					 * @returns Greater 0 when packet is incomplete, more data is needed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV int brymen_bm85x_packet_valid(void *st,
 | 
				
			||||||
 | 
						const uint8_t *buf, size_t len, size_t *pkt_len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t plen;
 | 
				
			||||||
 | 
						uint8_t cmd, crc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)st;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Four header bytes: DLE, STX, command, payload length. */
 | 
				
			||||||
 | 
						if (len < PKT_HEAD_LEN)
 | 
				
			||||||
 | 
							return SR_PACKET_NEED_RX;
 | 
				
			||||||
 | 
						if (read_u8_inc(&buf) != DLE)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						if (read_u8_inc(&buf) != STX)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						cmd = read_u8_inc(&buf);
 | 
				
			||||||
 | 
						/* Non-fatal, happens with OL pending during connect. */
 | 
				
			||||||
 | 
						if (cmd == 0x01)
 | 
				
			||||||
 | 
							cmd = 0x00;
 | 
				
			||||||
 | 
						if (cmd != CMD_GET_READING)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						plen = read_u8_inc(&buf);
 | 
				
			||||||
 | 
						if (plen > PKT_DATA_MAX)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						len -= PKT_HEAD_LEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Checksum spans bfunc and value text. Length according to header. */
 | 
				
			||||||
 | 
						if (len < plen + PKT_TAIL_LEN)
 | 
				
			||||||
 | 
							return SR_PACKET_NEED_RX;
 | 
				
			||||||
 | 
						crc = bm85x_crc(buf, plen);
 | 
				
			||||||
 | 
						buf += plen;
 | 
				
			||||||
 | 
						len -= plen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Three tail bytes: checksum, DLE, ETX. */
 | 
				
			||||||
 | 
						if (len < PKT_TAIL_LEN)
 | 
				
			||||||
 | 
							return SR_PACKET_NEED_RX;
 | 
				
			||||||
 | 
						if (read_u8_inc(&buf) != crc)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						if (read_u8_inc(&buf) != DLE)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
						if (read_u8_inc(&buf) != ETX)
 | 
				
			||||||
 | 
							return SR_PACKET_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Only return the total packet length when the receive buffer
 | 
				
			||||||
 | 
						 * was found to be valid. For invalid packets it's preferred to
 | 
				
			||||||
 | 
						 * have the caller keep trying to sync to the packet stream.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (pkt_len)
 | 
				
			||||||
 | 
							*pkt_len = PKT_HEAD_LEN + plen + PKT_TAIL_LEN;
 | 
				
			||||||
 | 
						return SR_PACKET_VALID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bm85x_flags {
 | 
				
			||||||
 | 
						gboolean is_batt, is_db, is_perc, is_hz, is_amp, is_beep;
 | 
				
			||||||
 | 
						gboolean is_ohm, is_temp_f, is_temp_c, is_diode, is_cap;
 | 
				
			||||||
 | 
						gboolean is_volt, is_dc, is_ac;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bm85x_parse_flags(const uint8_t *bfunc, struct bm85x_flags *flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!bfunc || !flags)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						memset(flags, 0, sizeof(*flags));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags->is_batt = bfunc[3] & (1u << 7);
 | 
				
			||||||
 | 
						if ((bfunc[3] & 0x7f) != 0)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((bfunc[2] & 0xff) != 0)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((bfunc[1] & 0xc0) != 0)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						flags->is_db = bfunc[1] & (1u << 5);
 | 
				
			||||||
 | 
						if ((bfunc[1] & 0x10) != 0)
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						flags->is_perc = bfunc[1] & (1u << 3);
 | 
				
			||||||
 | 
						flags->is_hz = bfunc[1] & (1u << 2);
 | 
				
			||||||
 | 
						flags->is_amp = bfunc[1] & (1u << 1);
 | 
				
			||||||
 | 
						flags->is_beep = bfunc[1] & (1u << 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags->is_ohm = bfunc[0] & (1u << 7);
 | 
				
			||||||
 | 
						flags->is_temp_f = bfunc[0] & (1u << 6);
 | 
				
			||||||
 | 
						flags->is_temp_c = bfunc[0] & (1u << 5);
 | 
				
			||||||
 | 
						flags->is_diode = bfunc[0] & (1u << 4);
 | 
				
			||||||
 | 
						flags->is_cap = bfunc[0] & (1u << 3);
 | 
				
			||||||
 | 
						flags->is_volt = bfunc[0] & (1u << 2);
 | 
				
			||||||
 | 
						flags->is_dc = bfunc[0] & (1u << 1);
 | 
				
			||||||
 | 
						flags->is_ac = bfunc[0] & (1u << 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bm85x_parse_value(char *txt, double *val, int *digits)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *src, *dst, c;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * See above comment on whitespace in response's number text.
 | 
				
			||||||
 | 
						 * The caller provides a NUL terminated writable text copy.
 | 
				
			||||||
 | 
						 * Go for low hanging fruit first (OL condition). Eliminate
 | 
				
			||||||
 | 
						 * whitespace then and do the number conversion.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (strstr(txt, "+OL")) {
 | 
				
			||||||
 | 
							*val = +INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strstr(txt, "-OL")) {
 | 
				
			||||||
 | 
							*val = -INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strstr(txt, "OL")) {
 | 
				
			||||||
 | 
							*val = INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						src = txt;
 | 
				
			||||||
 | 
						dst = txt;
 | 
				
			||||||
 | 
						while (*src) {
 | 
				
			||||||
 | 
							c = *src++;
 | 
				
			||||||
 | 
							if (c == ' ')
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							*dst++ = c;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*dst = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = sr_atod_ascii_digits(txt, val, digits);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int bm85x_parse_payload(const uint8_t *p, size_t l,
 | 
				
			||||||
 | 
						double *val, struct sr_datafeed_analog *analog)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const uint8_t *bfunc;
 | 
				
			||||||
 | 
						char text_buf[PKT_DATA_MAX], *text;
 | 
				
			||||||
 | 
						size_t text_len;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						struct bm85x_flags flags;
 | 
				
			||||||
 | 
						int digits;
 | 
				
			||||||
 | 
						char *parse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get a bfunc bits reference, and a writable value text. */
 | 
				
			||||||
 | 
						bfunc = &p[0];
 | 
				
			||||||
 | 
						text_len = l - PKT_BFUNC_LEN;
 | 
				
			||||||
 | 
						memcpy(text_buf, &p[PKT_BFUNC_LEN], text_len);
 | 
				
			||||||
 | 
						text_buf[text_len] = '\0';
 | 
				
			||||||
 | 
						text = &text_buf[0];
 | 
				
			||||||
 | 
						sr_dbg("DMM bfunc %02x %02x %02x %02x, text \"%s\"",
 | 
				
			||||||
 | 
							bfunc[0], bfunc[1], bfunc[2], bfunc[3], text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check 'bfunc' bitfield first, text interpretation depends on it. */
 | 
				
			||||||
 | 
						ret = bm85x_parse_flags(bfunc, &flags);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse the text after potential normalization/transformation. */
 | 
				
			||||||
 | 
						if (flags.is_db && flags.is_ohm) {
 | 
				
			||||||
 | 
							static const char *prefix = " 0.";
 | 
				
			||||||
 | 
							static const char *suffix = " E";
 | 
				
			||||||
 | 
							/* See above comment on dBm reference value text. */
 | 
				
			||||||
 | 
							if (strncmp(text, prefix, strlen(prefix)) != 0)
 | 
				
			||||||
 | 
								return SR_ERR_DATA;
 | 
				
			||||||
 | 
							text += strlen(prefix);
 | 
				
			||||||
 | 
							text_len -= strlen(prefix);
 | 
				
			||||||
 | 
							parse = strstr(text, suffix);
 | 
				
			||||||
 | 
							if (!parse)
 | 
				
			||||||
 | 
								return SR_ERR_DATA;
 | 
				
			||||||
 | 
							*parse = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_temp_f || flags.is_temp_c) {
 | 
				
			||||||
 | 
							/* See above comment on temperature value text. */
 | 
				
			||||||
 | 
							parse = strchr(text, flags.is_temp_f ? 'F' : 'C');
 | 
				
			||||||
 | 
							if (!parse)
 | 
				
			||||||
 | 
								return SR_ERR_DATA;
 | 
				
			||||||
 | 
							*parse = ' ';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						digits = 0;
 | 
				
			||||||
 | 
						ret = bm85x_parse_value(text, val, &digits);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fill in MQ and flags result details. */
 | 
				
			||||||
 | 
						analog->meaning->mqflags = 0;
 | 
				
			||||||
 | 
						if (flags.is_volt) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_amp) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_ohm) {
 | 
				
			||||||
 | 
							if (flags.is_db)
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							else if (flags.is_beep)
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_hz) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_perc) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_cap) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_temp_f) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_temp_c) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_db && !flags.is_ohm) {
 | 
				
			||||||
 | 
							/* See above comment on dBm measurements scale. */
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_POWER;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
				
			||||||
 | 
							*val *= 1000;
 | 
				
			||||||
 | 
							digits -= 3;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (flags.is_diode) {
 | 
				
			||||||
 | 
							/* See above comment on diode measurement responses. */
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (flags.is_ac)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
						if (flags.is_dc)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						analog->encoding->digits = digits;
 | 
				
			||||||
 | 
						analog->spec->spec_digits = digits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (flags.is_batt)
 | 
				
			||||||
 | 
							sr_warn("Low battery!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int brymen_bm85x_parse(void *st, const uint8_t *buf, size_t len,
 | 
				
			||||||
 | 
						double *val, struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const uint8_t *pl_ptr;
 | 
				
			||||||
 | 
						size_t pl_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)st;
 | 
				
			||||||
 | 
						(void)info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!buf || !len)
 | 
				
			||||||
 | 
							return SR_ERR_DATA;
 | 
				
			||||||
 | 
						if (!val || !analog)
 | 
				
			||||||
 | 
							return SR_ERR_DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (brymen_bm85x_packet_valid(NULL, buf, len, NULL) != SR_PACKET_VALID)
 | 
				
			||||||
 | 
							return SR_ERR_DATA;
 | 
				
			||||||
 | 
						pl_ptr = &buf[PKT_HEAD_LEN];
 | 
				
			||||||
 | 
						pl_len = len - PKT_HEAD_LEN - PKT_TAIL_LEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return bm85x_parse_payload(pl_ptr, pl_len, val, analog);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,356 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 Gerhard Sittig <gerhard.sittig@gmx.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Brymen BM86x serial protocol parser. The USB protocol (for the cable)
 | 
				
			||||||
 | 
					 * and the packet description (for the meter) were retrieved from:
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/Download2.html
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/PD02BM860s_protocolDL.html
 | 
				
			||||||
 | 
					 * http://brymen.com/product-html/images/DownloadList/ProtocolList/BM860-BM860s_List/BM860-BM860s-500000-count-dual-display-DMMs-protocol.pdf
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "brymen-bm86x"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
 | 
					SR_PRIV int sr_brymen_bm86x_packet_request(struct sr_serial_dev_inst *serial)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const uint8_t request[] = { 0x00, 0x00, 0x86, 0x66, };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						serial_write_nonblocking(serial, request, sizeof(request));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_brymen_bm86x_packet_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * "Model ID3" (3rd HID report, byte 3) is the only documented
 | 
				
			||||||
 | 
						 * fixed value, and must be 0x86. All other positions either depend
 | 
				
			||||||
 | 
						 * on the meter's function, or the measurement's value, or are not
 | 
				
			||||||
 | 
						 * documented by the vendor (are marked as "don't care", no fixed
 | 
				
			||||||
 | 
						 * values are listed). There is nothing else we can check reliably.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (buf[19] != 0x86)
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Data bytes in the DMM packet encode LCD segments in an unusual order
 | 
				
			||||||
 | 
					 * (bgcdafe) and in an unusual position (bits 7:1 within the byte). The
 | 
				
			||||||
 | 
					 * decimal point (bit 0) for one digit resides in the _next_ digit's byte.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * These routines convert LCD segments to characters, and a section of the
 | 
				
			||||||
 | 
					 * DMM packet (which corresponds to the primary or secondary display) to
 | 
				
			||||||
 | 
					 * the text representation of the measurement's value, before regular text
 | 
				
			||||||
 | 
					 * to number conversion is applied. The first byte of the passed in block
 | 
				
			||||||
 | 
					 * contains indicators, the value's digits start at the second byte.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char brymen_bm86x_parse_digit(uint8_t b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (b >> 1) {
 | 
				
			||||||
 | 
						/* Sign. */
 | 
				
			||||||
 | 
						case 0x20: return '-';
 | 
				
			||||||
 | 
						/* Decimal digits. */
 | 
				
			||||||
 | 
						case 0x5f: return '0';
 | 
				
			||||||
 | 
						case 0x50: return '1';
 | 
				
			||||||
 | 
						case 0x6d: return '2';
 | 
				
			||||||
 | 
						case 0x7c: return '3';
 | 
				
			||||||
 | 
						case 0x72: return '4';
 | 
				
			||||||
 | 
						case 0x3e: return '5';
 | 
				
			||||||
 | 
						case 0x3f: return '6';
 | 
				
			||||||
 | 
						case 0x54: return '7';
 | 
				
			||||||
 | 
						case 0x7f: return '8';
 | 
				
			||||||
 | 
						case 0x7e: return '9';
 | 
				
			||||||
 | 
						/* Temperature units. */
 | 
				
			||||||
 | 
						case 0x0f: return 'C';
 | 
				
			||||||
 | 
						case 0x27: return 'F';
 | 
				
			||||||
 | 
						/* OL condition, and diode mode. */
 | 
				
			||||||
 | 
						case 0x0b: return 'L';
 | 
				
			||||||
 | 
						case 0x79: return 'd';
 | 
				
			||||||
 | 
						case 0x10: return 'i';
 | 
				
			||||||
 | 
						case 0x39: return 'o';
 | 
				
			||||||
 | 
						/* Blank digit. */
 | 
				
			||||||
 | 
						case 0x00: return '\0';
 | 
				
			||||||
 | 
						/* Invalid or unknown segment combination. */
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							sr_warn("Unknown encoding for digit: 0x%02x.", b);
 | 
				
			||||||
 | 
							return '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int brymen_bm86x_parse_digits(const uint8_t *pkt, size_t pktlen,
 | 
				
			||||||
 | 
						char *txtbuf, float *value, char *temp_unit, int *digits, int signflag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t byte;
 | 
				
			||||||
 | 
						char *txtptr, txtchar;
 | 
				
			||||||
 | 
						size_t pos;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						txtptr = txtbuf;
 | 
				
			||||||
 | 
						if (digits)
 | 
				
			||||||
 | 
							*digits = INT_MIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pkt[0] & signflag)
 | 
				
			||||||
 | 
							*txtptr++ = '-';
 | 
				
			||||||
 | 
						for (pos = 0; pos < pktlen; pos++) {
 | 
				
			||||||
 | 
							byte = pkt[1 + pos];
 | 
				
			||||||
 | 
							if (pos && pos < 5 && (byte & 0x01)) {
 | 
				
			||||||
 | 
								*txtptr++ = '.';
 | 
				
			||||||
 | 
								if (digits)
 | 
				
			||||||
 | 
									*digits = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							txtchar = brymen_bm86x_parse_digit(byte);
 | 
				
			||||||
 | 
							if (pos == 5 && (txtchar == 'C' || txtchar == 'F')) {
 | 
				
			||||||
 | 
								if (temp_unit)
 | 
				
			||||||
 | 
									*temp_unit = txtchar;
 | 
				
			||||||
 | 
							} else if (txtchar) {
 | 
				
			||||||
 | 
								*txtptr++ = txtchar;
 | 
				
			||||||
 | 
								if (digits)
 | 
				
			||||||
 | 
									(*digits)++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*txtptr = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (digits && *digits < 0)
 | 
				
			||||||
 | 
							*digits = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = value ? sr_atof_ascii(txtbuf, value) : SR_OK;
 | 
				
			||||||
 | 
						if (ret != SR_OK) {
 | 
				
			||||||
 | 
							sr_dbg("invalid float string: '%s'", txtbuf);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Extract the measurement value and its properties for one of the
 | 
				
			||||||
 | 
					 * meter's displays from the DMM packet.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void brymen_bm86x_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
						struct sr_datafeed_analog *analog, size_t ch_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char txtbuf[16], temp_unit;
 | 
				
			||||||
 | 
						int ret, digits, is_diode, over_limit, scale;
 | 
				
			||||||
 | 
						uint8_t ind1, ind15;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						temp_unit = '\0';
 | 
				
			||||||
 | 
						if (ch_idx == 0) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Main display. Note that _some_ of the second display's
 | 
				
			||||||
 | 
							 * indicators are involved in the inspection of the _first_
 | 
				
			||||||
 | 
							 * display's measurement value. So we have to get the
 | 
				
			||||||
 | 
							 * second display's text buffer here, too.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							(void)brymen_bm86x_parse_digits(&buf[9], 4, txtbuf,
 | 
				
			||||||
 | 
								NULL, NULL, NULL, 0);
 | 
				
			||||||
 | 
							is_diode = strcmp(txtbuf, "diod") == 0;
 | 
				
			||||||
 | 
							ret = brymen_bm86x_parse_digits(&buf[2], 6, txtbuf,
 | 
				
			||||||
 | 
								floatval, &temp_unit, &digits, 0x80);
 | 
				
			||||||
 | 
							over_limit = strstr(txtbuf, "0L") || strstr(txtbuf, "0.L");
 | 
				
			||||||
 | 
							if (ret != SR_OK && !over_limit)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* SI unit. */
 | 
				
			||||||
 | 
							if (buf[8] & 0x01) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
								if (is_diode) {
 | 
				
			||||||
 | 
									analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
				
			||||||
 | 
									analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if (buf[14] & 0x80) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
							} else if (buf[14] & 0x20) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
 | 
							} else if (buf[14] & 0x10) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CONDUCTANCE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_SIEMENS;
 | 
				
			||||||
 | 
							} else if (buf[15] & 0x01) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
							} else if (buf[10] & 0x01) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
							} else if (buf[15] & 0x10) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
							} else if (buf[15] & 0x02) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_POWER;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
				
			||||||
 | 
							} else if (buf[15] & 0x80) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
							} else if ((buf[2] & 0x0a) && temp_unit) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
								if (temp_unit == 'F')
 | 
				
			||||||
 | 
									analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Remove the MIN/MAX/AVG indicators when all of them
 | 
				
			||||||
 | 
							 * are shown at the same time.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ind1 = buf[1];
 | 
				
			||||||
 | 
							if ((ind1 & 0xe0) == 0xe0)
 | 
				
			||||||
 | 
								ind1 &= ~0xe0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* AC/DC/Auto flags. */
 | 
				
			||||||
 | 
							if (buf[1] & 0x10)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
							if (buf[2] & 0x01)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
							if (buf[1] & 0x01)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
 | 
							if (buf[1] & 0x08)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
				
			||||||
 | 
							if (ind1 & 0x20)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_MAX;
 | 
				
			||||||
 | 
							if (ind1 & 0x40)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_MIN;
 | 
				
			||||||
 | 
							if (ind1 & 0x80)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_AVG;
 | 
				
			||||||
 | 
							if (buf[3] & 0x01)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_RELATIVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Remove the "dBm" indication's "m" indicator before the
 | 
				
			||||||
 | 
							 * SI unit's prefixes get inspected. To avoid an interaction
 | 
				
			||||||
 | 
							 * with the "milli" prefix.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ind15 = buf[15];
 | 
				
			||||||
 | 
							if (ind15 & 0x02)
 | 
				
			||||||
 | 
								ind15 &= ~0x04;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* SI prefix. */
 | 
				
			||||||
 | 
							scale = 0;
 | 
				
			||||||
 | 
							if (buf[14] & 0x40) /* n */
 | 
				
			||||||
 | 
								scale = -9;
 | 
				
			||||||
 | 
							if (buf[15] & 0x08) /* u */
 | 
				
			||||||
 | 
								scale = -6;
 | 
				
			||||||
 | 
							if (ind15 & 0x04) /* m */
 | 
				
			||||||
 | 
								scale = -3;
 | 
				
			||||||
 | 
							if (buf[15] & 0x40) /* k */
 | 
				
			||||||
 | 
								scale = +3;
 | 
				
			||||||
 | 
							if (buf[15] & 0x20) /* M */
 | 
				
			||||||
 | 
								scale = +6;
 | 
				
			||||||
 | 
							if (scale) {
 | 
				
			||||||
 | 
								*floatval *= pow(10, scale);
 | 
				
			||||||
 | 
								digits += -scale;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (over_limit)
 | 
				
			||||||
 | 
								*floatval = INFINITY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							analog->encoding->digits  = digits;
 | 
				
			||||||
 | 
							analog->spec->spec_digits = digits;
 | 
				
			||||||
 | 
						} else if (ch_idx == 1) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Secondary display. Also inspect _some_ primary display
 | 
				
			||||||
 | 
							 * data, to determine the secondary display's validity.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							(void)brymen_bm86x_parse_digits(&buf[2], 6, txtbuf,
 | 
				
			||||||
 | 
								NULL, &temp_unit, NULL, 0x80);
 | 
				
			||||||
 | 
							ret = brymen_bm86x_parse_digits(&buf[9], 4, txtbuf,
 | 
				
			||||||
 | 
								floatval, NULL, &digits, 0x10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* SI unit. */
 | 
				
			||||||
 | 
							if (buf[14] & 0x08) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
							} else if (buf[9] & 0x04) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
							} else if (buf[9] & 0x08) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
							} else if (buf[14] & 0x04) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
							} else if ((buf[9] & 0x40) && temp_unit) {
 | 
				
			||||||
 | 
								analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
								if (temp_unit == 'F')
 | 
				
			||||||
 | 
									analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* AC flag. */
 | 
				
			||||||
 | 
							if (buf[9] & 0x20)
 | 
				
			||||||
 | 
								analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* SI prefix. */
 | 
				
			||||||
 | 
							scale = 0;
 | 
				
			||||||
 | 
							if (buf[ 9] & 0x01) /* u */
 | 
				
			||||||
 | 
								scale = -6;
 | 
				
			||||||
 | 
							if (buf[ 9] & 0x02) /* m */
 | 
				
			||||||
 | 
								scale = -3;
 | 
				
			||||||
 | 
							if (buf[14] & 0x02) /* k */
 | 
				
			||||||
 | 
								scale = +3;
 | 
				
			||||||
 | 
							if (buf[14] & 0x01) /* M */
 | 
				
			||||||
 | 
								scale = +6;
 | 
				
			||||||
 | 
							if (scale) {
 | 
				
			||||||
 | 
								*floatval *= pow(10, scale);
 | 
				
			||||||
 | 
								digits += -scale;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							analog->encoding->digits  = digits;
 | 
				
			||||||
 | 
							analog->spec->spec_digits = digits;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buf[9] & 0x80)
 | 
				
			||||||
 | 
							sr_warn("Battery is low.");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int sr_brymen_bm86x_parse(const uint8_t *buf, float *val,
 | 
				
			||||||
 | 
						struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct brymen_bm86x_info *info_local;
 | 
				
			||||||
 | 
						size_t ch_idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Scan a portion of the received DMM packet which corresponds
 | 
				
			||||||
 | 
						 * to the caller's specified display. Then prepare to scan a
 | 
				
			||||||
 | 
						 * different portion of the packet for another display. This
 | 
				
			||||||
 | 
						 * routine gets called multiple times for one received packet.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						info_local = info;
 | 
				
			||||||
 | 
						ch_idx = info_local->ch_idx;
 | 
				
			||||||
 | 
						brymen_bm86x_parse(buf, val, analog, ch_idx);
 | 
				
			||||||
 | 
						info_local->ch_idx = ch_idx + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -254,6 +254,8 @@ static void parse_flags(const uint8_t *buf, struct dtm0660_info *info)
 | 
				
			||||||
static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
					static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
			 int *exponent, const struct dtm0660_info *info)
 | 
								 int *exponent, const struct dtm0660_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int initial_exponent = *exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Factors */
 | 
						/* Factors */
 | 
				
			||||||
	if (info->is_nano)
 | 
						if (info->is_nano)
 | 
				
			||||||
		*exponent -= 9;
 | 
							*exponent -= 9;
 | 
				
			||||||
| 
						 | 
					@ -265,7 +267,7 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
		*exponent += 3;
 | 
							*exponent += 3;
 | 
				
			||||||
	if (info->is_mega)
 | 
						if (info->is_mega)
 | 
				
			||||||
		*exponent += 6;
 | 
							*exponent += 6;
 | 
				
			||||||
	*floatval *= powf(10, *exponent);
 | 
						*floatval *= powf(10, (*exponent - initial_exponent));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Measurement modes */
 | 
						/* Measurement modes */
 | 
				
			||||||
	if (info->is_volt) {
 | 
						if (info->is_volt) {
 | 
				
			||||||
| 
						 | 
					@ -318,7 +320,7 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_hold)
 | 
						if (info->is_hold)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
				
			||||||
	if (info->is_rel)
 | 
						if (info->is_rel)
 | 
				
			||||||
| 
						 | 
					@ -373,7 +375,7 @@ SR_PRIV int sr_dtm0660_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct dtm0660_info *info_local;
 | 
						struct dtm0660_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct dtm0660_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
						if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
				
			||||||
		sr_dbg("Error parsing value: %d.", ret);
 | 
							sr_dbg("Error parsing value: %d.", ret);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -502,7 +502,7 @@ static void handle_flags(struct sr_datafeed_analog *analog,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_hold)
 | 
						if (info->is_hold)
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		* Note: HOLD only affects the number displayed on the LCD,
 | 
							* Note: HOLD only affects the number displayed on the LCD,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -302,7 +302,7 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_hold)
 | 
						if (info->is_hold)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
				
			||||||
	if (info->is_rel)
 | 
						if (info->is_rel)
 | 
				
			||||||
| 
						 | 
					@ -353,7 +353,7 @@ SR_PRIV int sr_fs9721_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
						if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
				
			||||||
		sr_dbg("Error parsing value: %d.", ret);
 | 
							sr_dbg("Error parsing value: %d.", ret);
 | 
				
			||||||
| 
						 | 
					@ -373,7 +373,7 @@ SR_PRIV void sr_fs9721_00_temp_c(struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined FS9721_LP3 flag 'c2c1_00' means temperature (C). */
 | 
						/* User-defined FS9721_LP3 flag 'c2c1_00' means temperature (C). */
 | 
				
			||||||
	if (info_local->is_c2c1_00) {
 | 
						if (info_local->is_c2c1_00) {
 | 
				
			||||||
| 
						 | 
					@ -386,7 +386,7 @@ SR_PRIV void sr_fs9721_01_temp_c(struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (C). */
 | 
						/* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (C). */
 | 
				
			||||||
	if (info_local->is_c2c1_01) {
 | 
						if (info_local->is_c2c1_01) {
 | 
				
			||||||
| 
						 | 
					@ -399,7 +399,7 @@ SR_PRIV void sr_fs9721_10_temp_c(struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined FS9721_LP3 flag 'c2c1_10' means temperature (C). */
 | 
						/* User-defined FS9721_LP3 flag 'c2c1_10' means temperature (C). */
 | 
				
			||||||
	if (info_local->is_c2c1_10) {
 | 
						if (info_local->is_c2c1_10) {
 | 
				
			||||||
| 
						 | 
					@ -412,7 +412,7 @@ SR_PRIV void sr_fs9721_01_10_temp_f_c(struct sr_datafeed_analog *analog, void *i
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (F). */
 | 
						/* User-defined FS9721_LP3 flag 'c2c1_01' means temperature (F). */
 | 
				
			||||||
	if (info_local->is_c2c1_01) {
 | 
						if (info_local->is_c2c1_01) {
 | 
				
			||||||
| 
						 | 
					@ -431,7 +431,7 @@ SR_PRIV void sr_fs9721_max_c_min(struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9721_info *info_local;
 | 
						struct fs9721_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9721_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined FS9721_LP3 flag 'c2c1_00' means MAX. */
 | 
						/* User-defined FS9721_LP3 flag 'c2c1_00' means MAX. */
 | 
				
			||||||
	if (info_local->is_c2c1_00)
 | 
						if (info_local->is_c2c1_00)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_hold)
 | 
						if (info->is_hold)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
				
			||||||
	if (info->is_max)
 | 
						if (info->is_max)
 | 
				
			||||||
| 
						 | 
					@ -359,7 +359,7 @@ SR_PRIV int sr_fs9922_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct fs9922_info *info_local;
 | 
						struct fs9922_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9922_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
						if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
 | 
				
			||||||
		sr_dbg("Error parsing value: %d.", ret);
 | 
							sr_dbg("Error parsing value: %d.", ret);
 | 
				
			||||||
| 
						 | 
					@ -379,12 +379,12 @@ SR_PRIV void sr_fs9922_z1_diode(struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fs9922_info *info_local;
 | 
						struct fs9922_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct fs9922_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* User-defined z1 flag means "diode mode". */
 | 
						/* User-defined z1 flag means "diode mode". */
 | 
				
			||||||
	if (info_local->is_z1) {
 | 
						if (info_local->is_z1) {
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_VOLT;
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ SR_PRIV gboolean sr_m2110_packet_valid(const uint8_t *buf)
 | 
				
			||||||
	if (!strncmp((const char *)buf, "OVERRNG", 7))
 | 
						if (!strncmp((const char *)buf, "OVERRNG", 7))
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sscanf((const char *)buf, "%f", &val) == 1)
 | 
						if (sr_atof_ascii((const char *)buf, &val) == SR_OK)
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strncmp((const char *)buf, "OVERRNG", 7))
 | 
						if (!strncmp((const char *)buf, "OVERRNG", 7))
 | 
				
			||||||
		*floatval = INFINITY;
 | 
							*floatval = INFINITY;
 | 
				
			||||||
	else if (sscanf((const char *)buf, "%f", &val) == 1) {
 | 
						else if (sr_atof_ascii((const char *)buf, &val) == SR_OK) {
 | 
				
			||||||
		*floatval = val;
 | 
							*floatval = val;
 | 
				
			||||||
		dot_pos = strcspn((const char *)buf, ".");
 | 
							dot_pos = strcspn((const char *)buf, ".");
 | 
				
			||||||
		if (dot_pos < 7)
 | 
							if (dot_pos < 7)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,6 @@
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Metex 14-bytes ASCII protocol parser.
 | 
					 * Metex 14-bytes ASCII protocol parser.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @internal
 | 
					 | 
				
			||||||
 * This should work for various multimeters which use this kind of protocol,
 | 
					 * This should work for various multimeters which use this kind of protocol,
 | 
				
			||||||
 * even though there is some variation in which modes each DMM supports.
 | 
					 * even though there is some variation in which modes each DMM supports.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -86,7 +85,7 @@ static int parse_value(const uint8_t *buf, struct metex14_info *info,
 | 
				
			||||||
		return SR_OK;
 | 
							return SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */
 | 
						/* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */
 | 
				
			||||||
	sscanf((const char *)&valstr, "%f", result);
 | 
						sr_atof_ascii((const char *)&valstr, result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dot_pos = strcspn(valstr, ".");
 | 
						dot_pos = strcspn(valstr, ".");
 | 
				
			||||||
	if (dot_pos < cnt)
 | 
						if (dot_pos < cnt)
 | 
				
			||||||
| 
						 | 
					@ -146,8 +145,14 @@ static void parse_flags(const char *buf, struct metex14_info *info)
 | 
				
			||||||
		info->is_kilo = info->is_hertz = TRUE;
 | 
							info->is_kilo = info->is_hertz = TRUE;
 | 
				
			||||||
	else if (!g_ascii_strcasecmp(u, "C"))
 | 
						else if (!g_ascii_strcasecmp(u, "C"))
 | 
				
			||||||
		info->is_celsius = TRUE;
 | 
							info->is_celsius = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "F"))
 | 
				
			||||||
 | 
							info->is_fahrenheit = TRUE;
 | 
				
			||||||
	else if (!g_ascii_strcasecmp(u, "DB"))
 | 
						else if (!g_ascii_strcasecmp(u, "DB"))
 | 
				
			||||||
		info->is_decibel = TRUE;
 | 
							info->is_decibel = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "dBm"))
 | 
				
			||||||
 | 
							info->is_decibel_mw = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "W"))
 | 
				
			||||||
 | 
							info->is_watt = TRUE;
 | 
				
			||||||
	else if (!g_ascii_strcasecmp(u, ""))
 | 
						else if (!g_ascii_strcasecmp(u, ""))
 | 
				
			||||||
		info->is_unitless = TRUE;
 | 
							info->is_unitless = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,15 +161,25 @@ static void parse_flags(const char *buf, struct metex14_info *info)
 | 
				
			||||||
		(!strncmp(buf, "  ", 2) && info->is_ohm);
 | 
							(!strncmp(buf, "  ", 2) && info->is_ohm);
 | 
				
			||||||
	info->is_capacity = !strncmp(buf, "CA", 2) ||
 | 
						info->is_capacity = !strncmp(buf, "CA", 2) ||
 | 
				
			||||||
		(!strncmp(buf, "  ", 2) && info->is_farad);
 | 
							(!strncmp(buf, "  ", 2) && info->is_farad);
 | 
				
			||||||
	info->is_temperature = !strncmp(buf, "TE", 2);
 | 
						info->is_temperature = !strncmp(buf, "TE", 2) ||
 | 
				
			||||||
 | 
							info->is_celsius || info->is_fahrenheit;
 | 
				
			||||||
	info->is_diode = !strncmp(buf, "DI", 2) ||
 | 
						info->is_diode = !strncmp(buf, "DI", 2) ||
 | 
				
			||||||
		(!strncmp(buf, "  ", 2) && info->is_volt && info->is_milli);
 | 
							(!strncmp(buf, "  ", 2) && info->is_volt && info->is_milli);
 | 
				
			||||||
	info->is_frequency = !strncmp(buf, "FR", 2) ||
 | 
						info->is_frequency = !strncmp(buf, "FR", 2) ||
 | 
				
			||||||
		(!strncmp(buf, "  ", 2) && info->is_hertz);
 | 
							(!strncmp(buf, "  ", 2) && info->is_hertz);
 | 
				
			||||||
	info->is_gain = !strncmp(buf, "DB", 2);
 | 
						info->is_gain = !strncmp(buf, "DB", 2) && info->is_decibel;
 | 
				
			||||||
 | 
						info->is_power = (!strncmp(buf, "dB", 2) && info->is_decibel_mw) ||
 | 
				
			||||||
 | 
							((!strncmp(buf, "WT", 2) && info->is_watt));
 | 
				
			||||||
 | 
						info->is_power_factor = !strncmp(buf, "CO", 2) && info->is_unitless;
 | 
				
			||||||
	info->is_hfe = !strncmp(buf, "HF", 2) ||
 | 
						info->is_hfe = !strncmp(buf, "HF", 2) ||
 | 
				
			||||||
		(!strncmp(buf, "  ", 2) && !info->is_volt && !info->is_ohm &&
 | 
							(!strncmp(buf, "  ", 2) && !info->is_ampere &&!info->is_volt &&
 | 
				
			||||||
		 !info->is_logic && !info->is_farad && !info->is_hertz);
 | 
							!info->is_resistance && !info->is_capacity && !info->is_frequency &&
 | 
				
			||||||
 | 
							!info->is_temperature && !info->is_power && !info->is_power_factor &&
 | 
				
			||||||
 | 
							!info->is_gain && !info->is_logic && !info->is_diode);
 | 
				
			||||||
 | 
						info->is_min = !strncmp(buf, "MN", 2);
 | 
				
			||||||
 | 
						info->is_max = !strncmp(buf, "MX", 2);
 | 
				
			||||||
 | 
						info->is_avg = !strncmp(buf, "AG", 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Note:
 | 
						 * Note:
 | 
				
			||||||
	 * - Protocol doesn't distinguish "resistance" from "beep" mode.
 | 
						 * - Protocol doesn't distinguish "resistance" from "beep" mode.
 | 
				
			||||||
| 
						 | 
					@ -178,8 +193,12 @@ static void parse_flags(const char *buf, struct metex14_info *info)
 | 
				
			||||||
static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
					static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
			 int *exponent, const struct metex14_info *info)
 | 
								 int *exponent, const struct metex14_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int factor = 0;
 | 
						int factor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Factors */
 | 
						/* Factors */
 | 
				
			||||||
 | 
						factor = 0;
 | 
				
			||||||
	if (info->is_pico)
 | 
						if (info->is_pico)
 | 
				
			||||||
		factor -= 12;
 | 
							factor -= 12;
 | 
				
			||||||
	if (info->is_nano)
 | 
						if (info->is_nano)
 | 
				
			||||||
| 
						 | 
					@ -193,7 +212,6 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_mega)
 | 
						if (info->is_mega)
 | 
				
			||||||
		factor += 6;
 | 
							factor += 6;
 | 
				
			||||||
	*floatval *= powf(10, factor);
 | 
						*floatval *= powf(10, factor);
 | 
				
			||||||
	*exponent += factor;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Measurement modes */
 | 
						/* Measurement modes */
 | 
				
			||||||
	if (info->is_volt) {
 | 
						if (info->is_volt) {
 | 
				
			||||||
| 
						 | 
					@ -216,14 +234,32 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
							analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_FARAD;
 | 
							analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (info->is_celsius) {
 | 
						if (info->is_temperature) {
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
							analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							if (info->is_celsius)
 | 
				
			||||||
			analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
								analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
							else if (info->is_fahrenheit)
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_UNITLESS;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (info->is_diode) {
 | 
						if (info->is_diode) {
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_VOLT;
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_power) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_POWER;
 | 
				
			||||||
 | 
							if (info->is_decibel_mw)
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
				
			||||||
 | 
							else if (info->is_watt)
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_WATT;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								analog->meaning->unit = SR_UNIT_UNITLESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_power_factor) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_POWER_FACTOR;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_UNITLESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (info->is_gain) {
 | 
						if (info->is_gain) {
 | 
				
			||||||
		analog->meaning->mq = SR_MQ_GAIN;
 | 
							analog->meaning->mq = SR_MQ_GAIN;
 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_DECIBEL_VOLT;
 | 
							analog->meaning->unit = SR_UNIT_DECIBEL_VOLT;
 | 
				
			||||||
| 
						 | 
					@ -243,7 +279,13 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
	if (info->is_dc)
 | 
						if (info->is_dc)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						if (info->is_min)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_MIN;
 | 
				
			||||||
 | 
						if (info->is_max)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_MAX;
 | 
				
			||||||
 | 
						if (info->is_avg)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AVG;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static gboolean flags_valid(const struct metex14_info *info)
 | 
					static gboolean flags_valid(const struct metex14_info *info)
 | 
				
			||||||
| 
						 | 
					@ -286,14 +328,23 @@ static gboolean flags_valid(const struct metex14_info *info)
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_LIBSERIALPORT
 | 
					#ifdef HAVE_SERIAL_COMM
 | 
				
			||||||
SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial)
 | 
					SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const uint8_t wbuf = 'D';
 | 
						const uint8_t wbuf = 'D';
 | 
				
			||||||
 | 
						size_t wrlen;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_spew("Requesting DMM packet.");
 | 
						sr_spew("Requesting DMM packet.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (serial_write_nonblocking(serial, &wbuf, 1) == 1) ? SR_OK : SR_ERR;
 | 
						wrlen = sizeof(wbuf);
 | 
				
			||||||
 | 
						ret = serial_write_blocking(serial, &wbuf, wrlen, 0);
 | 
				
			||||||
 | 
						if (ret < 0)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						if ((size_t)ret != wrlen)
 | 
				
			||||||
 | 
							return SR_ERR_IO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -313,6 +364,25 @@ SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf)
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_metex14_4packets_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct metex14_info info;
 | 
				
			||||||
 | 
						size_t ch_idx;
 | 
				
			||||||
 | 
						const uint8_t *ch_buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch_buf = buf;
 | 
				
			||||||
 | 
						for (ch_idx = 0; ch_idx < 4; ch_idx++) {
 | 
				
			||||||
 | 
							if (ch_buf[13] != '\r')
 | 
				
			||||||
 | 
								return FALSE;
 | 
				
			||||||
 | 
							memset(&info, 0x00, sizeof(info));
 | 
				
			||||||
 | 
							parse_flags((const char *)ch_buf, &info);
 | 
				
			||||||
 | 
							if (!flags_valid(&info))
 | 
				
			||||||
 | 
								return FALSE;
 | 
				
			||||||
 | 
							ch_buf += METEX14_PACKET_SIZE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Parse a protocol packet.
 | 
					 * Parse a protocol packet.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -334,7 +404,7 @@ SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct metex14_info *info_local;
 | 
						struct metex14_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct metex14_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Don't print byte 13. That one contains the carriage return. */
 | 
						/* Don't print byte 13. That one contains the carriage return. */
 | 
				
			||||||
	sr_dbg("DMM packet: \"%.13s\"", buf);
 | 
						sr_dbg("DMM packet: \"%.13s\"", buf);
 | 
				
			||||||
| 
						 | 
					@ -354,3 +424,34 @@ SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parse one out of four values of a four-display Metex14 variant.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The caller's 'info' parameter can be used to track the channel index,
 | 
				
			||||||
 | 
					 * as long as the information is kept across calls to the 14-byte packet
 | 
				
			||||||
 | 
					 * parse routine (which clears the 'info' container).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Since analog values have further details in the 'analog' parameter,
 | 
				
			||||||
 | 
					 * passing multiple values per parse routine call is problematic. So we
 | 
				
			||||||
 | 
					 * prefer the approach of passing one value per call, which is most
 | 
				
			||||||
 | 
					 * reliable and shall fit every similar device with multiple displays.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The meters which use this parse routine send one 14-byte packet per
 | 
				
			||||||
 | 
					 * display. Each packet has the regular Metex14 layout.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV int sr_metex14_4packets_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
						struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct metex14_info *info_local;
 | 
				
			||||||
 | 
						size_t ch_idx;
 | 
				
			||||||
 | 
						const uint8_t *ch_buf;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info_local = info;
 | 
				
			||||||
 | 
						ch_idx = info_local->ch_idx;
 | 
				
			||||||
 | 
						ch_buf = buf + ch_idx * METEX14_PACKET_SIZE;
 | 
				
			||||||
 | 
						rc = sr_metex14_parse(ch_buf, floatval, analog, info);
 | 
				
			||||||
 | 
						info_local->ch_idx = ch_idx + 1;
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,457 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Peter Skarpetis <peters@skarpetis.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Meterman 38XR protocol parser
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Communication parameters: Unidirectional, 9600/8n1
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The user guide can be downloaded from:
 | 
				
			||||||
 | 
					 * https://assets.tequipment.net/assets/1/26/Documents/38XR_Manual.pdf
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Protocol is described in a PDF available at:
 | 
				
			||||||
 | 
					 * https://www.elfadistrelec.fi/Web/Downloads/od/es/fj38XR-Serial-Output-Codes.pdf
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * There is also a disussion about the protocol at the NI forum:
 | 
				
			||||||
 | 
					 * https://forums.ni.com/t5/Digital-Multimeters-DMMs-and/Meterman-DMM/td-p/179597?profile.language=en
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * EEVBlog discussion thread about the meter
 | 
				
			||||||
 | 
					 * https://www.eevblog.com/forum/chat/meterman-38xr/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Meterman 38XR ASCII protocol parser.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "mm38xr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define METERMAN_DIGITS_OVERLOAD 0xb0dd
 | 
				
			||||||
 | 
					#define METERMAN_DIGITS_BAD_INPUT_JACK 0xbaab
 | 
				
			||||||
 | 
					#define METERMAN_BARGRAPH_NO_SEGMENTS = 0x2a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum mm38xr_func_code {
 | 
				
			||||||
 | 
						FUNC_CODE_UNUSED = 0x01,
 | 
				
			||||||
 | 
						FUNC_CODE_TEMPERATURE_FARENHEIGHT = 0x02,
 | 
				
			||||||
 | 
						FUNC_CODE_CURRENT_4_20_MAMPS = 0x03, /* 4-20 mA */
 | 
				
			||||||
 | 
						FUNC_CODE_DIODE_TEST = 0x04,
 | 
				
			||||||
 | 
						FUNC_CODE_INDUCTANCE_HENRIES = 0x05,
 | 
				
			||||||
 | 
						FUNC_CODE_TEMPERATURE_CELSIUS = 0x06,
 | 
				
			||||||
 | 
						FUNC_CODE_CURRENT_UAMPS = 0x07, /* uA */
 | 
				
			||||||
 | 
						FUNC_CODE_RESISTANCE_OHMS = 0x08,
 | 
				
			||||||
 | 
						FUNC_CODE_INDUCTANCE_MHENRIES = 0x09, /* mH */
 | 
				
			||||||
 | 
						FUNC_CODE_CURRENT_10_AMPS = 0x0a,
 | 
				
			||||||
 | 
						FUNC_CODE_CAPACITANCE = 0x0b,
 | 
				
			||||||
 | 
						FUNC_CODE_VOLTS_DC = 0x0c,
 | 
				
			||||||
 | 
						FUNC_CODE_LOGIC = 0x0d,
 | 
				
			||||||
 | 
						FUNC_CODE_CURRENT_MAMPS = 0x0e, /* mA */
 | 
				
			||||||
 | 
						FUNC_CODE_FREQUENCY_HZ = 0x0f, /* and duty cycle */
 | 
				
			||||||
 | 
						FUNC_CODE_VOLTS_AC = 0x10, /* and dBm */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum mm38xr_meas_mode {
 | 
				
			||||||
 | 
						/* This is used to index into the digits and exponent arrays below. */
 | 
				
			||||||
 | 
						MEAS_MODE_VOLTS,
 | 
				
			||||||
 | 
						MEAS_MODE_RESISTANCE_OHMS,
 | 
				
			||||||
 | 
						MEAS_MODE_CURRENT_UAMPS, /* uA */
 | 
				
			||||||
 | 
						MEAS_MODE_CURRENT_MAMPS, /* mA */
 | 
				
			||||||
 | 
						MEAS_MODE_CURRENT_AMPS,
 | 
				
			||||||
 | 
						MEAS_MODE_CAPACITANCE,
 | 
				
			||||||
 | 
						MEAS_MODE_DIODE_TEST,
 | 
				
			||||||
 | 
						MEAS_MODE_TEMPERATURE_C,
 | 
				
			||||||
 | 
						MEAS_MODE_TEMPERATURE_F,
 | 
				
			||||||
 | 
						MEAS_MODE_FREQUENCY_HZ,
 | 
				
			||||||
 | 
						MEAS_MODE_INDUCTANCE_H,
 | 
				
			||||||
 | 
						MEAS_MODE_INDUCTANCE_MH, /* mH */
 | 
				
			||||||
 | 
						MEAS_MODE_DBM,
 | 
				
			||||||
 | 
						MEAS_MODE_DUTY_CYCLE,
 | 
				
			||||||
 | 
						MEAS_MODE_CONTINUITY,
 | 
				
			||||||
 | 
						/* For internal purposes. */
 | 
				
			||||||
 | 
						MEAS_MODE_UNDEFINED,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum mm38xr_adcd_mode {
 | 
				
			||||||
 | 
						ACDC_MODE_NONE = 1000,
 | 
				
			||||||
 | 
						ACDC_MODE_DC,
 | 
				
			||||||
 | 
						ACDC_MODE_AC,
 | 
				
			||||||
 | 
						ACDC_MODE_AC_AND_DC,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct meterman_info {
 | 
				
			||||||
 | 
						enum mm38xr_func_code functioncode; /* columns 0, 1 */
 | 
				
			||||||
 | 
						unsigned int reading;               /* columns 2,3,4,5; LCD digits */
 | 
				
			||||||
 | 
						unsigned int bargraphsegments;      /* columns 6, 7; max 40 segments, 0x2A = no bargraph */
 | 
				
			||||||
 | 
						size_t rangecode;                   /* column 8 */
 | 
				
			||||||
 | 
						unsigned int ampsfunction;          /* column 9 */
 | 
				
			||||||
 | 
						unsigned int peakstatus;            /* column 10 */
 | 
				
			||||||
 | 
						unsigned int rflag_h;               /* column 11 */
 | 
				
			||||||
 | 
						unsigned int rflag_l;               /* column 12 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* calculated values */
 | 
				
			||||||
 | 
						enum mm38xr_meas_mode meas_mode;
 | 
				
			||||||
 | 
						enum mm38xr_adcd_mode acdc;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int decimal_digits[][7] = {
 | 
				
			||||||
 | 
						[MEAS_MODE_VOLTS]           = { 1, 3, 2, 1, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_RESISTANCE_OHMS] = { 2, 3, 4, 2, 3, 1, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_UAMPS]   = { 2, 1, 0, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_MAMPS]   = { 3, 2, 1, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_AMPS]    = { 3, 0, 0, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CAPACITANCE]     = { 2, 1, 3, 2, 1, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DIODE_TEST]      = { 0, 3, 0, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_TEMPERATURE_C]   = { 0, 0, 0, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_TEMPERATURE_F]   = { 0, 0, 0, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_FREQUENCY_HZ]    = { 2, 1, 3, 2, 1, 3, 2, },
 | 
				
			||||||
 | 
						[MEAS_MODE_INDUCTANCE_H]    = { 0, 0, 0, 3, 2, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_INDUCTANCE_MH]   = { 3, 2, 1, 0, 0, 0, 0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DBM]             = { 2, 2, 2, 2, 2, 2, 2, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DUTY_CYCLE]      = { 2, 2, 2, 2, 2, 2, 2, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CONTINUITY]      = { 0, 0, 0, 0, 0, 1, 0, },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int units_exponents[][7] = {
 | 
				
			||||||
 | 
						[MEAS_MODE_VOLTS]           = { -3,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_RESISTANCE_OHMS] = {  6,  6,  6,  3,  3,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_UAMPS]   = { -6, -6,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_MAMPS]   = { -3, -3, -3,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CURRENT_AMPS]    = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CAPACITANCE]     = { -9, -9, -6, -6, -6,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DIODE_TEST]      = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_TEMPERATURE_C]   = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_TEMPERATURE_F]   = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_FREQUENCY_HZ]    = {  0,  0,  3,  3,  3,  6,  6, },
 | 
				
			||||||
 | 
						[MEAS_MODE_INDUCTANCE_H]    = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_INDUCTANCE_MH]   = { -3, -3, -3,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DBM]             = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_DUTY_CYCLE]      = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
						[MEAS_MODE_CONTINUITY]      = {  0,  0,  0,  0,  0,  0,  0, },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Assumes caller has already checked data fall within 0..9 and A..F */
 | 
				
			||||||
 | 
					static uint32_t meterman_38xr_hexnibble_to_uint(uint8_t v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (v <= '9') ? v - '0' : v - 'A' + 10;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t meterman_38xr_func_code(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v = meterman_38xr_hexnibble_to_uint(buf[0]) << 4 |
 | 
				
			||||||
 | 
							meterman_38xr_hexnibble_to_uint(buf[1]);
 | 
				
			||||||
 | 
						return v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t meterman_38xr_barsegments(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v = meterman_38xr_hexnibble_to_uint(buf[6]) << 4 |
 | 
				
			||||||
 | 
							meterman_38xr_hexnibble_to_uint(buf[7]);
 | 
				
			||||||
 | 
						return v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint32_t meterman_38xr_reading(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buf[2] > 'A') { /* overload */
 | 
				
			||||||
 | 
							v = meterman_38xr_hexnibble_to_uint(buf[2]) << 12 |
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[3]) << 8 |
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[4]) << 4 |
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[5]) << 0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							v = meterman_38xr_hexnibble_to_uint(buf[2]) * 1000 +
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[3]) * 100 +
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[4]) * 10 +
 | 
				
			||||||
 | 
								meterman_38xr_hexnibble_to_uint(buf[5]) * 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean meterman_38xr_is_negative(struct meterman_info *mi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mi->rflag_l == 0x01)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						if (mi->meas_mode == MEAS_MODE_DBM && mi->rflag_l == 0x05)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int currentACDC(struct meterman_info *mi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mi->ampsfunction == 0x01)
 | 
				
			||||||
 | 
							return ACDC_MODE_AC;
 | 
				
			||||||
 | 
						if (mi->ampsfunction == 0x02)
 | 
				
			||||||
 | 
							return ACDC_MODE_AC_AND_DC;
 | 
				
			||||||
 | 
						return ACDC_MODE_DC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int meterman_38xr_decode(const uint8_t *buf, struct meterman_info *mi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!meterman_38xr_packet_valid(buf))
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mi->functioncode = meterman_38xr_func_code(buf);
 | 
				
			||||||
 | 
						if (mi->functioncode < 2 || mi->functioncode > 0x10)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						mi->reading = meterman_38xr_reading(buf);
 | 
				
			||||||
 | 
						mi->bargraphsegments = meterman_38xr_barsegments(buf);
 | 
				
			||||||
 | 
						mi->rangecode = meterman_38xr_hexnibble_to_uint(buf[8]);
 | 
				
			||||||
 | 
						if (mi->rangecode > 6)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						mi->ampsfunction = meterman_38xr_hexnibble_to_uint(buf[9]);
 | 
				
			||||||
 | 
						mi->peakstatus = meterman_38xr_hexnibble_to_uint(buf[10]);
 | 
				
			||||||
 | 
						mi->rflag_h = meterman_38xr_hexnibble_to_uint(buf[11]);
 | 
				
			||||||
 | 
						mi->rflag_l = meterman_38xr_hexnibble_to_uint(buf[12]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mi->acdc = ACDC_MODE_NONE;
 | 
				
			||||||
 | 
						switch (mi->functioncode) {
 | 
				
			||||||
 | 
						case FUNC_CODE_TEMPERATURE_FARENHEIGHT:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_TEMPERATURE_F;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_CURRENT_4_20_MAMPS:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_CURRENT_MAMPS;
 | 
				
			||||||
 | 
							mi->acdc = currentACDC(mi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_DIODE_TEST:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_DIODE_TEST;
 | 
				
			||||||
 | 
							mi->acdc = ACDC_MODE_DC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_INDUCTANCE_HENRIES:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_INDUCTANCE_H;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_TEMPERATURE_CELSIUS:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_TEMPERATURE_C;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_CURRENT_UAMPS:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_CURRENT_UAMPS;
 | 
				
			||||||
 | 
							mi->acdc = currentACDC(mi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_RESISTANCE_OHMS:
 | 
				
			||||||
 | 
							mi->meas_mode = (mi->rflag_l == 0x08)
 | 
				
			||||||
 | 
								? MEAS_MODE_CONTINUITY
 | 
				
			||||||
 | 
								: MEAS_MODE_RESISTANCE_OHMS;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_INDUCTANCE_MHENRIES:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_INDUCTANCE_MH;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_CURRENT_10_AMPS:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_CURRENT_AMPS;
 | 
				
			||||||
 | 
							mi->acdc = currentACDC(mi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_CAPACITANCE:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_CAPACITANCE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_VOLTS_DC:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_VOLTS;
 | 
				
			||||||
 | 
							mi->acdc = (mi->rflag_l == 0x02)
 | 
				
			||||||
 | 
								? ACDC_MODE_AC_AND_DC : ACDC_MODE_DC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_CURRENT_MAMPS:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_CURRENT_MAMPS;
 | 
				
			||||||
 | 
							mi->acdc = currentACDC(mi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_FREQUENCY_HZ:
 | 
				
			||||||
 | 
							mi->meas_mode = (mi->rflag_h == 0x0B)
 | 
				
			||||||
 | 
								? MEAS_MODE_DUTY_CYCLE
 | 
				
			||||||
 | 
								: MEAS_MODE_FREQUENCY_HZ;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FUNC_CODE_VOLTS_AC:
 | 
				
			||||||
 | 
							mi->meas_mode = (mi->rflag_l == 0x04 || mi->rflag_l == 0x05)
 | 
				
			||||||
 | 
								? MEAS_MODE_DBM : MEAS_MODE_VOLTS;
 | 
				
			||||||
 | 
							mi->acdc = ACDC_MODE_AC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							mi->meas_mode = MEAS_MODE_UNDEFINED;
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean meterman_38xr_packet_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
						uint32_t fcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((buf[13] != '\r') || (buf[14] != '\n'))
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check for all hex digits */
 | 
				
			||||||
 | 
						for (i = 0; i < 13; i++) {
 | 
				
			||||||
 | 
							if (buf[i] < '0')
 | 
				
			||||||
 | 
								return FALSE;
 | 
				
			||||||
 | 
							if (buf[i] > '9' && buf[i] < 'A')
 | 
				
			||||||
 | 
								return FALSE;
 | 
				
			||||||
 | 
							if (buf[i] > 'F')
 | 
				
			||||||
 | 
								return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fcode = meterman_38xr_func_code(buf);
 | 
				
			||||||
 | 
						if (fcode < 0x01 || fcode > 0x10)
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int meterman_38xr_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
						struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						gboolean is_overload, is_bad_jack;
 | 
				
			||||||
 | 
						int exponent;
 | 
				
			||||||
 | 
						int digits;
 | 
				
			||||||
 | 
						struct meterman_info mi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (meterman_38xr_decode(buf, &mi) != SR_OK)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mi.meas_mode != MEAS_MODE_CONTINUITY) {
 | 
				
			||||||
 | 
							is_overload = mi.reading == METERMAN_DIGITS_OVERLOAD;
 | 
				
			||||||
 | 
							is_bad_jack = mi.reading == METERMAN_DIGITS_BAD_INPUT_JACK;
 | 
				
			||||||
 | 
							if (is_overload || is_bad_jack) {
 | 
				
			||||||
 | 
								sr_spew("Over limit.");
 | 
				
			||||||
 | 
								*floatval = INFINITY; /* overload */
 | 
				
			||||||
 | 
								return SR_OK;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch (mi.meas_mode) {
 | 
				
			||||||
 | 
						case MEAS_MODE_VOLTS:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_RESISTANCE_OHMS:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_CURRENT_UAMPS:
 | 
				
			||||||
 | 
						case MEAS_MODE_CURRENT_MAMPS:
 | 
				
			||||||
 | 
						case MEAS_MODE_CURRENT_AMPS:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_CAPACITANCE:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_DIODE_TEST:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_TEMPERATURE_C:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_TEMPERATURE_F:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_FREQUENCY_HZ:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_INDUCTANCE_H:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_SERIES_INDUCTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HENRY;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_INDUCTANCE_MH:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_SERIES_INDUCTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HENRY;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_DBM:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_DUTY_CYCLE:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MEAS_MODE_CONTINUITY:
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_BOOLEAN;
 | 
				
			||||||
 | 
							*floatval = (mi.reading == METERMAN_DIGITS_OVERLOAD) ? 0.0 : 1.0;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch (mi.acdc) {
 | 
				
			||||||
 | 
						case ACDC_MODE_DC:
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case ACDC_MODE_AC:
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case ACDC_MODE_AC_AND_DC:
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC | SR_MQFLAG_AC;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (mi.peakstatus == 0x02 || mi.peakstatus == 0x0a)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_MAX;
 | 
				
			||||||
 | 
						if (mi.peakstatus == 0x03 || mi.peakstatus == 0x0b)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_MIN;
 | 
				
			||||||
 | 
						if (mi.rflag_h == 0x0a || mi.peakstatus == 0x0b)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
 | 
						if (mi.meas_mode != MEAS_MODE_CONTINUITY) {
 | 
				
			||||||
 | 
							digits = decimal_digits[mi.meas_mode][mi.rangecode];
 | 
				
			||||||
 | 
							exponent = units_exponents[mi.meas_mode][mi.rangecode];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*floatval = mi.reading;
 | 
				
			||||||
 | 
							if (meterman_38xr_is_negative(&mi)) {
 | 
				
			||||||
 | 
								*floatval *= -1.0f;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*floatval *= powf(10, -digits);
 | 
				
			||||||
 | 
							*floatval *= powf(10, exponent);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						analog->encoding->digits = 4;
 | 
				
			||||||
 | 
						analog->spec->spec_digits = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,374 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2019 Vitaliy Vorobyov
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					 * MASTECH MS2115B protocol parser.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Sends 9 bytes.
 | 
				
			||||||
 | 
					 * D0 D1 D2 D3 D4 D5 D6 D7 D8 D9
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D0 = 0x55 - sync byte
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D1 - mode:
 | 
				
			||||||
 | 
					 * bits:
 | 
				
			||||||
 | 
					 * B7..B4 ??
 | 
				
			||||||
 | 
					 * B3 - func
 | 
				
			||||||
 | 
					 * B2..B0:
 | 
				
			||||||
 | 
					 * 0 - A 600/1000 (func=0 AC, func=1 DC), signed
 | 
				
			||||||
 | 
					 * 1 - A 60 (func=0 AC, func=1 DC), signed
 | 
				
			||||||
 | 
					 * 2 - V (func=0 AC, func=1 DC), signed
 | 
				
			||||||
 | 
					 * 3 - diode/beep (func=0 buz, func=1 diode)
 | 
				
			||||||
 | 
					 * 4 - resistance
 | 
				
			||||||
 | 
					 * 5 - capacitance
 | 
				
			||||||
 | 
					 * 6 - hz
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D2 - range
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D3 - frq range
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D4 main value LSB
 | 
				
			||||||
 | 
					 * D5 main value MSB
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (secondary value, hz, min/max, rel)
 | 
				
			||||||
 | 
					 * D6 secondary value LSB
 | 
				
			||||||
 | 
					 * D7 secondary value MSB
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * D8 - flags
 | 
				
			||||||
 | 
					 * bits:
 | 
				
			||||||
 | 
					 * B7..B1:??
 | 
				
			||||||
 | 
					 * B0 - 0 - auto, 1 - manual
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * resistance:
 | 
				
			||||||
 | 
					 * 55 04 00 00 9B 18 00 00 01 (0.L, manual) 600.0 Ohm (x 0.1)
 | 
				
			||||||
 | 
					 * 55 04 01 00 9B 18 00 00 01 (0.L, manual) 6.000 kOhm (x 0.001)
 | 
				
			||||||
 | 
					 * 55 04 02 00 9B 18 00 00 01 (0.L, manual) 60.00 kOhm (x 0.01)
 | 
				
			||||||
 | 
					 * 55 04 03 00 9B 18 00 00 01 (0.L, manual) 600.0 kOhm (x 0.1)
 | 
				
			||||||
 | 
					 * 55 04 04 00 9B 18 00 00 01 (0.L, manual) 6.000 MOhm (x 0.001)
 | 
				
			||||||
 | 
					 * 55 04 05 00 9B 18 00 00 00 (0.L, auto)   60.00 MOhm (x 0.01)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * capacitance:
 | 
				
			||||||
 | 
					 * 55 05 00 00 04 00 00 00 00 (4nF, auto)
 | 
				
			||||||
 | 
					 * 55 05 00 00 05 00 00 00 01 (5nF, manual)      6.000 nF (x 0.001)
 | 
				
			||||||
 | 
					 * 55 05 01 00 03 19 00 00 01 (0.L nF, manual)   60.00 nF (x 0.01)
 | 
				
			||||||
 | 
					 * 55 05 02 00 D4 03 00 00 01 (980.0 nF, manual) 600.0 nF (x 0.1)
 | 
				
			||||||
 | 
					 * 55 05 03 00 63 00 00 00 01 (0.099 uF, manual) 6.000 uF (x 0.001)
 | 
				
			||||||
 | 
					 * 55 05 04 00 40 18 00 00 01 (0.L uF, manual)
 | 
				
			||||||
 | 
					 * 55 05 04 00 F0 00 00 00 01 (2.40 uF, manual)  60.00 uF (x 0.01)
 | 
				
			||||||
 | 
					 * 55 05 05 00 17 00 00 00 01 (2.3 uF, manual)   600.0 uF (x 0.1)
 | 
				
			||||||
 | 
					 * 55 05 06 00 02 00 00 00 01 (0.002 mF, manual) 6.000 mF (x 0.001)
 | 
				
			||||||
 | 
					 * 55 05 07 00 2F 00 00 00 01 (0.47 mF, manual)  60.00 mF (x 0.01)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * voltage:
 | 
				
			||||||
 | 
					 * 55 02 00 00 00 00 00 00 01 (0.0mV, manual)  600.0 mV (x 0.1)
 | 
				
			||||||
 | 
					 * 55 02 01 00 00 00 00 00 00 (0.000V, auto)
 | 
				
			||||||
 | 
					 * 55 02 01 00 00 00 00 00 01 (0.000V, manual) 6.000 V  (x 0.001)
 | 
				
			||||||
 | 
					 * 55 02 02 00 00 00 00 00 01 (0.00V, manual)  60.00 V  (x 0.01)
 | 
				
			||||||
 | 
					 * 55 02 03 00 00 00 00 00 01 (0.0V, manual)   600.0 V  (x 0.1)
 | 
				
			||||||
 | 
					 * 55 02 04 00 00 00 00 00 01 (0V, manual)     1000  V  (x 1)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - Communication parameters: Unidirectional, 1200/8n1
 | 
				
			||||||
 | 
					 * - CP2102 USB to UART bridge controller
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "ms2115b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
 | 
						const struct ms2115b_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Measurement modes */
 | 
				
			||||||
 | 
						if (info->is_volt) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ampere) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ohm) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_hz) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_farad) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_beep) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_BOOLEAN;
 | 
				
			||||||
 | 
							*floatval = (*floatval == INFINITY) ? 0.0 : 1.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_diode) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->is_duty_cycle)
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->is_percent)
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Measurement related flags */
 | 
				
			||||||
 | 
						if (info->is_ac)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
						if (info->is_dc)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						if (info->is_auto)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
 | 
						if (info->is_diode)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_ms2115b_packet_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sr_dbg("DMM packet: %02x %02x %02x %02x %02x %02x %02x %02x %02x",
 | 
				
			||||||
 | 
							buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
 | 
				
			||||||
 | 
							buf[7], buf[8]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buf[0] == 0x55)
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Mode values equal to received data */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						MODE_A600_1000 = 0,
 | 
				
			||||||
 | 
						MODE_A60 = 1,
 | 
				
			||||||
 | 
						MODE_V = 2,
 | 
				
			||||||
 | 
						MODE_DIODE_BEEP = 3,
 | 
				
			||||||
 | 
						MODE_OHM = 4,
 | 
				
			||||||
 | 
						MODE_CAP = 5,
 | 
				
			||||||
 | 
						MODE_HZ = 6,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int res_exp[] = {
 | 
				
			||||||
 | 
						-1,     /* 600.0 Ohm  (x 0.1)   */
 | 
				
			||||||
 | 
						-3 + 3, /* 6.000 kOhm (x 0.001) */
 | 
				
			||||||
 | 
						-2 + 3, /* 60.00 kOhm (x 0.01)  */
 | 
				
			||||||
 | 
						-1 + 3, /* 600.0 kOhm (x 0.1)   */
 | 
				
			||||||
 | 
						-3 + 6, /* 6.000 MOhm (x 0.001) */
 | 
				
			||||||
 | 
						-2 + 6, /* 60.00 MOhm (x 0.01)  */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int cap_exp[] = {
 | 
				
			||||||
 | 
						-3 - 9, /* 6.000 nF (x 0.001) */
 | 
				
			||||||
 | 
						-2 - 9, /* 60.00 nF (x 0.01)  */
 | 
				
			||||||
 | 
						-1 - 9, /* 600.0 nF (x 0.1)   */
 | 
				
			||||||
 | 
						-3 - 6, /* 6.000 uF (x 0.001) */
 | 
				
			||||||
 | 
						-2 - 6, /* 60.00 uF (x 0.01)  */
 | 
				
			||||||
 | 
						-1 - 6, /* 600.0 uF (x 0.1)   */
 | 
				
			||||||
 | 
						-3 - 3, /* 6.000 mF (x 0.001) */
 | 
				
			||||||
 | 
						-2 - 3, /* 60.00 mF (x 0.01)  */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int hz_exp[] = {
 | 
				
			||||||
 | 
						-2,     /* 60.00 Hz  (x 0.01)  */
 | 
				
			||||||
 | 
						-1,     /* 600.0 Hz  (x 0.1)   */
 | 
				
			||||||
 | 
						-3 + 3, /* 6.000 kHz (x 0.001) */
 | 
				
			||||||
 | 
						-2 + 3, /* 60.00 kHz (x 0.01)  */
 | 
				
			||||||
 | 
						-1 + 3, /* 600.0 kHz (x 0.1)   */
 | 
				
			||||||
 | 
						-3 + 6, /* 6.000 MHz (x 0.001) */
 | 
				
			||||||
 | 
						-2 + 6, /* 60.00 MHz (x 0.01)  */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int v_exp[] = {
 | 
				
			||||||
 | 
						-1 - 3, /* 600.0 mV (x 0.1)   */
 | 
				
			||||||
 | 
						-3,     /* 6.000 V  (x 0.001) */
 | 
				
			||||||
 | 
						-2,     /* 60.00 V  (x 0.01)  */
 | 
				
			||||||
 | 
						-1,     /* 600.0 V  (x 0.1)   */
 | 
				
			||||||
 | 
						0,      /* 1000  V  (x 1)     */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const char *ms2115b_channel_formats[MS2115B_DISPLAY_COUNT] = {
 | 
				
			||||||
 | 
						"main", "sub",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ms2115b_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
						struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int exponent = 0;
 | 
				
			||||||
 | 
						float up_limit = 6000.0;
 | 
				
			||||||
 | 
						gboolean sign = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t mode = (buf[1] & 7);
 | 
				
			||||||
 | 
						gboolean func = (buf[1] & 8) ? TRUE : FALSE;
 | 
				
			||||||
 | 
						uint32_t range = (buf[2] & 7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ms2115b_info *info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum eev121gw_display display = info_local->ch_idx;
 | 
				
			||||||
 | 
						memset(info_local, 0, sizeof(*info_local));
 | 
				
			||||||
 | 
						info_local->ch_idx = display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (display) {
 | 
				
			||||||
 | 
						case MS2115B_DISPLAY_MAIN:
 | 
				
			||||||
 | 
							switch (mode) {
 | 
				
			||||||
 | 
							case MODE_A600_1000:
 | 
				
			||||||
 | 
								exponent = -1;
 | 
				
			||||||
 | 
								sign = TRUE;
 | 
				
			||||||
 | 
								info_local->is_ampere = TRUE;
 | 
				
			||||||
 | 
								if (func)
 | 
				
			||||||
 | 
									info_local->is_dc = TRUE;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									info_local->is_ac = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_A60:
 | 
				
			||||||
 | 
								exponent = -2;
 | 
				
			||||||
 | 
								sign = TRUE;
 | 
				
			||||||
 | 
								info_local->is_ampere = TRUE;
 | 
				
			||||||
 | 
								if (func)
 | 
				
			||||||
 | 
									info_local->is_dc = TRUE;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									info_local->is_ac = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_V:
 | 
				
			||||||
 | 
								if (range >= ARRAY_SIZE(v_exp))
 | 
				
			||||||
 | 
									return SR_ERR;
 | 
				
			||||||
 | 
								exponent = v_exp[range];
 | 
				
			||||||
 | 
								sign = TRUE;
 | 
				
			||||||
 | 
								info_local->is_volt = TRUE;
 | 
				
			||||||
 | 
								if (func)
 | 
				
			||||||
 | 
									info_local->is_dc = TRUE;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									info_local->is_ac = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_DIODE_BEEP:
 | 
				
			||||||
 | 
								if (func) {
 | 
				
			||||||
 | 
									exponent = -3;
 | 
				
			||||||
 | 
									up_limit = 2500.0;
 | 
				
			||||||
 | 
									info_local->is_diode = TRUE;
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									info_local->is_beep = TRUE;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_OHM:
 | 
				
			||||||
 | 
								if (range >= ARRAY_SIZE(res_exp))
 | 
				
			||||||
 | 
									return SR_ERR;
 | 
				
			||||||
 | 
								exponent = res_exp[range];
 | 
				
			||||||
 | 
								info_local->is_ohm = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_CAP:
 | 
				
			||||||
 | 
								if (range >= ARRAY_SIZE(cap_exp))
 | 
				
			||||||
 | 
									return SR_ERR;
 | 
				
			||||||
 | 
								exponent = cap_exp[range];
 | 
				
			||||||
 | 
								info_local->is_farad = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_HZ:
 | 
				
			||||||
 | 
								range = (buf[3] & 7);
 | 
				
			||||||
 | 
								if (range >= ARRAY_SIZE(hz_exp))
 | 
				
			||||||
 | 
									return SR_ERR;
 | 
				
			||||||
 | 
								exponent = hz_exp[range];
 | 
				
			||||||
 | 
								info_local->is_hz = TRUE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (sign) {
 | 
				
			||||||
 | 
								*floatval = RL16S(buf + 4); /* signed 16bit value */
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								*floatval = RL16(buf + 4); /* unsigned 16bit value */
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							info_local->is_auto = (buf[8] & 1) ? FALSE : TRUE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case MS2115B_DISPLAY_SUB:
 | 
				
			||||||
 | 
							switch (mode) {
 | 
				
			||||||
 | 
							case MODE_A600_1000:
 | 
				
			||||||
 | 
							case MODE_A60:
 | 
				
			||||||
 | 
							case MODE_V:
 | 
				
			||||||
 | 
								if (func) /* DC */
 | 
				
			||||||
 | 
									return SR_ERR_NA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* AC */
 | 
				
			||||||
 | 
								info_local->is_hz = TRUE;
 | 
				
			||||||
 | 
								exponent = -2;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case MODE_HZ:
 | 
				
			||||||
 | 
								info_local->is_duty_cycle = TRUE;
 | 
				
			||||||
 | 
								info_local->is_percent = TRUE;
 | 
				
			||||||
 | 
								exponent = -1;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return SR_ERR_NA;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*floatval = RL16(buf + 6); /* unsigned 16bit value */
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fabsf(*floatval) > up_limit) {
 | 
				
			||||||
 | 
							sr_spew("Over limit.");
 | 
				
			||||||
 | 
							*floatval = INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*floatval *= powf(10, exponent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						handle_flags(analog, floatval, info_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						analog->encoding->digits = -exponent;
 | 
				
			||||||
 | 
						analog->spec->spec_digits = -exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parse a protocol packet.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param buf Buffer containing the 9-byte protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param floatval Pointer to a float variable. That variable will contain the
 | 
				
			||||||
 | 
					 *                 result value upon parsing success. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param analog Pointer to a struct sr_datafeed_analog. The struct will be
 | 
				
			||||||
 | 
					 *               filled with data according to the protocol packet.
 | 
				
			||||||
 | 
					 *               Must not be NULL.
 | 
				
			||||||
 | 
					 * @param info Pointer to a struct ms2115b_info. The struct will be filled
 | 
				
			||||||
 | 
					 *             with data according to the protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the
 | 
				
			||||||
 | 
					 *         'analog' variable contents are undefined and should not be used.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV int sr_ms2115b_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
							struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						int ch_idx;
 | 
				
			||||||
 | 
						struct ms2115b_info *info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ch_idx = info_local->ch_idx;
 | 
				
			||||||
 | 
						ret = ms2115b_parse(buf, floatval, analog, info);
 | 
				
			||||||
 | 
						info_local->ch_idx = ch_idx + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,389 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
 | 
				
			||||||
 | 
					 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 Stefan Mandl
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * MASTECH MS8250D protocol parser.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Sends 18 bytes.
 | 
				
			||||||
 | 
					 * 40 02 32 75 53 33 35 5303 10 00 00 00 00 00 00 10 00
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - Communication parameters: Unidirectional, 2400/8n1
 | 
				
			||||||
 | 
					 * - CP2102 USB to UART bridge controller
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "ms8250d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Main display (7-segment LCD value): xxDGA xxEF xxxx xxCB
 | 
				
			||||||
 | 
					 * https://en.wikipedia.org/wiki/Seven-segment_display
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int parse_digit(uint16_t b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (b) {
 | 
				
			||||||
 | 
						case 0x0: /* 7-segment not active */
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						case 0x430: /* Overflow */
 | 
				
			||||||
 | 
							return 0xF;
 | 
				
			||||||
 | 
						case 0x533:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						case 0x003:
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						case 0x721:
 | 
				
			||||||
 | 
							return 2;
 | 
				
			||||||
 | 
						case 0x703:
 | 
				
			||||||
 | 
							return 3;
 | 
				
			||||||
 | 
						case 0x213:
 | 
				
			||||||
 | 
							return 4;
 | 
				
			||||||
 | 
						case 0x712:
 | 
				
			||||||
 | 
							return 5;
 | 
				
			||||||
 | 
						case 0x732:
 | 
				
			||||||
 | 
							return 6;
 | 
				
			||||||
 | 
						case 0x103:
 | 
				
			||||||
 | 
							return 7;
 | 
				
			||||||
 | 
						case 0x733:
 | 
				
			||||||
 | 
							return 8;
 | 
				
			||||||
 | 
						case 0x713:
 | 
				
			||||||
 | 
							return 9;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							sr_dbg("Invalid digit word: 0x%04x.", b);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Parse second display. */
 | 
				
			||||||
 | 
					static int parse_digit2(uint16_t b)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (b) {
 | 
				
			||||||
 | 
						case 0x00:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						case 0x7D:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						case 0x05:
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						case 0x1B:
 | 
				
			||||||
 | 
							return 2;
 | 
				
			||||||
 | 
						case 0x1F:
 | 
				
			||||||
 | 
							return 3;
 | 
				
			||||||
 | 
						case 0x27:
 | 
				
			||||||
 | 
							return 4;
 | 
				
			||||||
 | 
						case 0x3E:
 | 
				
			||||||
 | 
							return 5;
 | 
				
			||||||
 | 
						case 0x7E:
 | 
				
			||||||
 | 
							return 6;
 | 
				
			||||||
 | 
						case 0x15:
 | 
				
			||||||
 | 
							return 7;
 | 
				
			||||||
 | 
						case 0x7F:
 | 
				
			||||||
 | 
							return 8;
 | 
				
			||||||
 | 
						case 0x3F:
 | 
				
			||||||
 | 
							return 9;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							sr_dbg("Invalid second display digit word: 0x%04x.", b);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void parse_flags(const uint8_t *buf, struct ms8250d_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						info->is_volt   = (buf[9]  & (1 << 4)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_ohm    = (buf[9]  & (1 << 6)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_ampere = (buf[10] & (1 << 0)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_hz     = (buf[10] & (1 << 2)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_farad  = (buf[10] & (1 << 1)) ? 1 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Micro */
 | 
				
			||||||
 | 
						if (!info->is_farad)
 | 
				
			||||||
 | 
							info->is_micro = (buf[8] & (1 << 4)) ? 1 : 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							info->is_micro = (buf[9] & (1 << 1)) ? 1 : 0; /* uF */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info->is_nano  = (buf[8] & (1 << 5)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_milli = (buf[9] & (1 << 0)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_kilo  = (buf[9] & (1 << 2)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_mega  = (buf[8] & (1 << 6)) ? 1 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info->is_autotimer = (buf[1]  & (1 << 0)) ? 1 : 0; /* Auto off timer */
 | 
				
			||||||
 | 
						info->is_rs232     = (buf[1]  & (1 << 1)) ? 1 : 0; /* RS232 via USB */
 | 
				
			||||||
 | 
						info->is_ac        = (buf[1]  & (1 << 4)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_dc        = (buf[2]  & (1 << 1)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_auto      = (buf[16] & (1 << 4)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_bat       = (buf[1]  & (1 << 5)) ? 1 : 0; /* Low battery */
 | 
				
			||||||
 | 
						info->is_min       = (buf[16] & (1 << 2)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_max       = (buf[16] & (1 << 1)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_rel       = (buf[15] & (1 << 7)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_hold      = (buf[16] & (1 << 3)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_diode     = (buf[11] & (1 << 0)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_beep      = (buf[11] & (1 << 1)) ? 1 : 0;
 | 
				
			||||||
 | 
						info->is_ncv       = (buf[0]  & (1 << 0)) ? 1 : 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean flags_valid(const struct ms8250d_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Does the packet have more than one multiplier? */
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						count += (info->is_nano) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_micro) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_milli) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_kilo) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_mega) ? 1 : 0;
 | 
				
			||||||
 | 
						if (count > 1) {
 | 
				
			||||||
 | 
							sr_dbg("More than one multiplier detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Does the packet "measure" more than one type of value? */
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						count += (info->is_hz) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_ohm) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_farad) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_ampere) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_volt) ? 1 : 0;
 | 
				
			||||||
 | 
						if (count > 1) {
 | 
				
			||||||
 | 
							sr_dbg("More than one measurement type detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Both AC and DC set? */
 | 
				
			||||||
 | 
						if (info->is_ac && info->is_dc) {
 | 
				
			||||||
 | 
							sr_dbg("Both AC and DC flags detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RS232 flag set? */
 | 
				
			||||||
 | 
						if (!info->is_rs232) {
 | 
				
			||||||
 | 
							sr_dbg("No RS232 flag detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
 | 
							int *exponent, const struct ms8250d_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* Factors */
 | 
				
			||||||
 | 
						if (info->is_nano)
 | 
				
			||||||
 | 
							*exponent -= 9;
 | 
				
			||||||
 | 
						if (info->is_micro)
 | 
				
			||||||
 | 
							*exponent -= 6;
 | 
				
			||||||
 | 
						if (info->is_milli)
 | 
				
			||||||
 | 
							*exponent -= 3;
 | 
				
			||||||
 | 
						if (info->is_kilo)
 | 
				
			||||||
 | 
							*exponent += 3;
 | 
				
			||||||
 | 
						if (info->is_mega)
 | 
				
			||||||
 | 
							*exponent += 6;
 | 
				
			||||||
 | 
						*floatval *= powf(10, *exponent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Measurement modes */
 | 
				
			||||||
 | 
						if (info->is_volt) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ampere) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ohm) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_hz) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_HERTZ;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_farad) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_FARAD;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_beep) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_BOOLEAN;
 | 
				
			||||||
 | 
							*floatval = (*floatval == INFINITY) ? 0.0 : 1.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_diode) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_percent) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Measurement related flags */
 | 
				
			||||||
 | 
						if (info->is_ac)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
						if (info->is_dc)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						if (info->is_auto)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
 | 
						if (info->is_diode)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						if (info->is_hold)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
				
			||||||
 | 
						if (info->is_rel)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_RELATIVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Other flags */
 | 
				
			||||||
 | 
						if (info->is_rs232)
 | 
				
			||||||
 | 
							sr_spew("RS232 enabled.");
 | 
				
			||||||
 | 
						if (info->is_bat)
 | 
				
			||||||
 | 
							sr_spew("Battery is low.");
 | 
				
			||||||
 | 
						if (info->is_beep)
 | 
				
			||||||
 | 
							sr_spew("Beep is active");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_ms8250d_packet_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct ms8250d_info info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("DMM packet: %02x %02x %02x %02x %02x %02x %02x "
 | 
				
			||||||
 | 
							"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
 | 
				
			||||||
 | 
							buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
 | 
				
			||||||
 | 
							buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13],
 | 
				
			||||||
 | 
							buf[14], buf[15], buf[16], buf[17]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parse_flags(buf, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((buf[17] == 0x00) && flags_valid(&info))
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parse a protocol packet.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param buf Buffer containing the 18-byte protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param floatval Pointer to a float variable. That variable will contain the
 | 
				
			||||||
 | 
					 *                 result value upon parsing success. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param analog Pointer to a struct sr_datafeed_analog. The struct will be
 | 
				
			||||||
 | 
					 *               filled with data according to the protocol packet.
 | 
				
			||||||
 | 
					 *               Must not be NULL.
 | 
				
			||||||
 | 
					 * @param info Pointer to a struct ms8250d_info. The struct will be filled
 | 
				
			||||||
 | 
					 *             with data according to the protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the
 | 
				
			||||||
 | 
					 *         'analog' variable contents are undefined and should not be used.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV int sr_ms8250d_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
							struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int exponent = 0, sec_exponent = 0, sign;
 | 
				
			||||||
 | 
						float sec_floatval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* buf[0] bar display. */
 | 
				
			||||||
 | 
						/* buf[1] bar display. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse seven segment digit. */
 | 
				
			||||||
 | 
						int16_t digit4 = parse_digit(((buf[7] & 0x73) << 4) | (buf[8] & 0x3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int16_t digit3 = parse_digit(((buf[6] & 0x07) << 8) | (buf[5] & 0x30) \
 | 
				
			||||||
 | 
										| ((buf[6] & 0x30) >> 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int16_t digit2 = parse_digit(((buf[4] & 0x73) << 4) | (buf[5] & 0x03));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int16_t digit1 = parse_digit(((buf[3] & 0x07) << 8) | (buf[2] & 0x30) \
 | 
				
			||||||
 | 
										| ((buf[3] & 0x30) >> 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("Digits: %d %d %d %d.", digit1, digit2, digit3, digit4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Decimal point position. */
 | 
				
			||||||
 | 
						if ((buf[3] & (1 << 6)) != 0) {
 | 
				
			||||||
 | 
							exponent = -3;
 | 
				
			||||||
 | 
							sr_spew("Decimal point after first digit.");
 | 
				
			||||||
 | 
						} else if ((buf[5] & (1 << 6)) != 0) {
 | 
				
			||||||
 | 
							exponent = -2;
 | 
				
			||||||
 | 
							sr_spew("Decimal point after second digit.");
 | 
				
			||||||
 | 
						} else if ((buf[7] & (1 << 2)) != 0) {
 | 
				
			||||||
 | 
							exponent = -1;
 | 
				
			||||||
 | 
							sr_spew("Decimal point after third digit.");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							exponent = 0;
 | 
				
			||||||
 | 
							sr_spew("No decimal point in the number.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ms8250d_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parse_flags(buf, info_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Sign */
 | 
				
			||||||
 | 
						sign = (buf[0] & (1 << 2)) ? -1 : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse second display. */
 | 
				
			||||||
 | 
						int16_t sec_digit4 = parse_digit2(buf[12] & 0x7F);
 | 
				
			||||||
 | 
						int16_t sec_digit3 = parse_digit2(buf[13] & 0x7F);
 | 
				
			||||||
 | 
						int16_t sec_digit2 = parse_digit2(buf[14] & 0x7F);
 | 
				
			||||||
 | 
						int16_t sec_digit1 = parse_digit2(buf[15] & 0x7F);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_dbg("Digits (2nd display): %d %d %d %d.",
 | 
				
			||||||
 | 
							sec_digit1, sec_digit2, sec_digit3, sec_digit4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Second display decimal point position. */
 | 
				
			||||||
 | 
						if ((buf[14] & (1 << 7)) != 0) {
 | 
				
			||||||
 | 
							sec_exponent = -3;
 | 
				
			||||||
 | 
							sr_spew("Sec decimal point after first digit.");
 | 
				
			||||||
 | 
						} else if ((buf[13] & (1 << 7)) != 0) {
 | 
				
			||||||
 | 
							sec_exponent = -2;
 | 
				
			||||||
 | 
							sr_spew("Sec decimal point after second digit.");
 | 
				
			||||||
 | 
						} else if ((buf[12] & (1 << 7)) != 0) {
 | 
				
			||||||
 | 
							sec_exponent = -1;
 | 
				
			||||||
 | 
							sr_spew("Sec decimal point after third digit.");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							sec_exponent = 0;
 | 
				
			||||||
 | 
							sr_spew("Sec no decimal point in the number.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*floatval = (double)((digit1 * 1000) + (digit2 * 100) + (digit3 * 10) + digit4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sec_floatval = (double)(sec_digit1 * 1000) + (sec_digit2 * 100) + (sec_digit3 * 10) + sec_digit4;
 | 
				
			||||||
 | 
						sec_floatval *= powf(10, sec_exponent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Apply sign. */
 | 
				
			||||||
 | 
						*floatval *= sign;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						handle_flags(analog, floatval, &exponent, info_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check for "OL". */
 | 
				
			||||||
 | 
						if (digit3 == 0x0F) {
 | 
				
			||||||
 | 
							sr_spew("Over limit.");
 | 
				
			||||||
 | 
							*floatval = INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("The display value is %f.", (double)*floatval);
 | 
				
			||||||
 | 
						sr_spew("The 2nd display value is %f.", sec_floatval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						analog->encoding->digits = -exponent;
 | 
				
			||||||
 | 
						analog->spec->spec_digits = -exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -284,7 +284,7 @@ static void handle_flags(struct sr_datafeed_analog *analog,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static gboolean flags_valid(const struct ut71x_info *info)
 | 
					static gboolean flags_valid(const struct ut71x_info *info)
 | 
				
			||||||
| 
						 | 
					@ -336,7 +336,7 @@ SR_PRIV int sr_ut71x_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct ut71x_info *info_local;
 | 
						struct ut71x_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct ut71x_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
	memset(info_local, 0, sizeof(struct ut71x_info));
 | 
						memset(info_local, 0, sizeof(struct ut71x_info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sr_ut71x_packet_valid(buf))
 | 
						if (!sr_ut71x_packet_valid(buf))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,7 +360,7 @@ static void handle_flags(struct sr_datafeed_analog *analog,
 | 
				
			||||||
	if (info->is_auto)
 | 
						if (info->is_auto)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
				
			||||||
	if (info->is_diode)
 | 
						if (info->is_diode)
 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	if (info->is_hold)
 | 
						if (info->is_hold)
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Note: HOLD only affects the number displayed on the LCD,
 | 
							 * Note: HOLD only affects the number displayed on the LCD,
 | 
				
			||||||
| 
						 | 
					@ -410,7 +410,7 @@ SR_PRIV int sr_vc870_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
	int ret, exponent = 0;
 | 
						int ret, exponent = 0;
 | 
				
			||||||
	struct vc870_info *info_local;
 | 
						struct vc870_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info_local = (struct vc870_info *)info;
 | 
						info_local = info;
 | 
				
			||||||
	memset(info_local, 0, sizeof(struct vc870_info));
 | 
						memset(info_local, 0, sizeof(struct vc870_info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sr_vc870_packet_valid(buf))
 | 
						if (!sr_vc870_packet_valid(buf))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,288 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2012-2013 Uwe Hermann <uwe@hermann-uwe.de>
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 Matthias Schulz <matthschulz@arcor.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Voltcraft 13-bytes ASCII protocol parser.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Bytes 1-3 measuring mode, byte 4 '-' for negative,
 | 
				
			||||||
 | 
					 * bytes 5-9 value, bytes 10-11 unit, bytes 12-13 CRLF 0d 0a.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <strings.h>
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_PREFIX "vc96"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Parse value from buf, byte 3-8. */
 | 
				
			||||||
 | 
					static int parse_value(const uint8_t *buf, struct vc96_info *info,
 | 
				
			||||||
 | 
								float *result, int *exponent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, is_ol, cnt, dot_pos;
 | 
				
			||||||
 | 
						char valstr[8 + 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Strip all spaces from bytes 3-8. */
 | 
				
			||||||
 | 
						memset(&valstr, 0, 6 + 1);
 | 
				
			||||||
 | 
						for (i = 0, cnt = 0; i < 6; i++) {
 | 
				
			||||||
 | 
							if (buf[3 + i] != ' ')
 | 
				
			||||||
 | 
								valstr[cnt++] = buf[3 + i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 5-7: Over limit (various forms) */
 | 
				
			||||||
 | 
						is_ol = 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, ".OL")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "O.L")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "OL.")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "OL")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-.OL")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-O.L")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-OL.")) ? 1 : 0;
 | 
				
			||||||
 | 
						is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-OL")) ? 1 : 0;
 | 
				
			||||||
 | 
						if (is_ol != 0) {
 | 
				
			||||||
 | 
							sr_spew("Over limit.");
 | 
				
			||||||
 | 
							*result = INFINITY;
 | 
				
			||||||
 | 
							return SR_OK;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 3-10: Sign, value (up to 5 digits) and decimal point */
 | 
				
			||||||
 | 
						sr_atof_ascii((const char *)&valstr, result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dot_pos = strcspn(valstr, ".");
 | 
				
			||||||
 | 
						if (dot_pos < cnt)
 | 
				
			||||||
 | 
							*exponent = -(cnt - dot_pos - 1);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							*exponent = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("The display value is %f.", *result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void parse_flags(const char *buf, struct vc96_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, cnt;
 | 
				
			||||||
 | 
						char unit[4 + 1];
 | 
				
			||||||
 | 
						const char *u;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 0-1: Measurement mode AC, DC */
 | 
				
			||||||
 | 
						info->is_ac = !strncmp(buf, "AC", 2);
 | 
				
			||||||
 | 
						info->is_dc = !strncmp(buf, "DC", 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 0-2: Measurement mode DIO, OHM */
 | 
				
			||||||
 | 
						info->is_ohm = !strncmp(buf, "OHM", 3);
 | 
				
			||||||
 | 
						info->is_diode = !strncmp(buf, "DIO", 3);
 | 
				
			||||||
 | 
						info->is_hfe = !strncmp(buf, "hfe", 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 3-8: See parse_value(). */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Strip all spaces from bytes 9-10. */
 | 
				
			||||||
 | 
						memset(&unit, 0, 2 + 1);
 | 
				
			||||||
 | 
						for (i = 0, cnt = 0; i < 2; i++) {
 | 
				
			||||||
 | 
							if (buf[9 + i] != ' ')
 | 
				
			||||||
 | 
								unit[cnt++] = buf[9 + i];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sr_spew("Bytes 9..10 without spaces \"%.4s\".", unit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 9-10: Unit */
 | 
				
			||||||
 | 
						u = (const char *)&unit;
 | 
				
			||||||
 | 
						if (!g_ascii_strcasecmp(u, "A"))
 | 
				
			||||||
 | 
							info->is_ampere = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "mA"))
 | 
				
			||||||
 | 
							info->is_milli = info->is_ampere = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "uA"))
 | 
				
			||||||
 | 
							info->is_micro = info->is_ampere = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "V"))
 | 
				
			||||||
 | 
							info->is_volt = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "mV"))
 | 
				
			||||||
 | 
							info->is_milli = info->is_volt = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "K"))
 | 
				
			||||||
 | 
							info->is_kilo = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, "M"))
 | 
				
			||||||
 | 
							info->is_mega = TRUE;
 | 
				
			||||||
 | 
						else if (!g_ascii_strcasecmp(u, ""))
 | 
				
			||||||
 | 
							info->is_unitless = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes 0-2: Measurement mode, except AC/DC */
 | 
				
			||||||
 | 
						info->is_resistance = !strncmp(buf, "OHM", 3) ||
 | 
				
			||||||
 | 
							(!strncmp(buf, "  ", 3) && info->is_ohm);
 | 
				
			||||||
 | 
						info->is_diode = !strncmp(buf, "DIO", 3) ||
 | 
				
			||||||
 | 
							(!strncmp(buf, "  ", 3) && info->is_volt && info->is_milli);
 | 
				
			||||||
 | 
						info->is_hfe = !strncmp(buf, "hfe", 3) ||
 | 
				
			||||||
 | 
							(!strncmp(buf, "  ", 3) && !info->is_ampere && !info->is_volt &&
 | 
				
			||||||
 | 
							!info->is_resistance && !info->is_diode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Note:
 | 
				
			||||||
 | 
						 * - Protocol doesn't distinguish "resistance" from "beep" mode.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Byte 12: Always '\r' (carriage return, 0x0d, 12) */
 | 
				
			||||||
 | 
						/* Byte 13: Always '\n' (carriage return, 0x0a, 13) */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_flags(struct sr_datafeed_analog *analog, float *floatval,
 | 
				
			||||||
 | 
								 int *exponent, const struct vc96_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int factor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(void)exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Factors */
 | 
				
			||||||
 | 
						factor = 0;
 | 
				
			||||||
 | 
						if (info->is_micro)
 | 
				
			||||||
 | 
							factor -= 6;
 | 
				
			||||||
 | 
						if (info->is_milli)
 | 
				
			||||||
 | 
							factor -= 3;
 | 
				
			||||||
 | 
						if (info->is_kilo)
 | 
				
			||||||
 | 
							factor += 3;
 | 
				
			||||||
 | 
						if (info->is_mega)
 | 
				
			||||||
 | 
							factor += 6;
 | 
				
			||||||
 | 
						*floatval *= powf(10, factor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Measurement modes */
 | 
				
			||||||
 | 
						if (info->is_volt) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ampere) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_ohm) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_OHM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_diode) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_VOLT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (info->is_hfe) {
 | 
				
			||||||
 | 
							analog->meaning->mq = SR_MQ_GAIN;
 | 
				
			||||||
 | 
							analog->meaning->unit = SR_UNIT_UNITLESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Measurement related flags */
 | 
				
			||||||
 | 
						if (info->is_ac)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
				
			||||||
 | 
						if (info->is_dc)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
						if (info->is_diode)
 | 
				
			||||||
 | 
							analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean flags_valid(const struct vc96_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Does the packet have more than one multiplier? */
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						count += (info->is_micro) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_milli) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_kilo) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_mega) ? 1 : 0;
 | 
				
			||||||
 | 
						if (count > 1) {
 | 
				
			||||||
 | 
							sr_dbg("More than one multiplier detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Does the packet "measure" more than one type of value? */
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						count += (info->is_ac) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_dc) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_resistance) ? 1 : 0;
 | 
				
			||||||
 | 
						count += (info->is_diode) ? 1 : 0;
 | 
				
			||||||
 | 
						if (count > 1) {
 | 
				
			||||||
 | 
							sr_dbg("More than one measurement type detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Both AC and DC set? */
 | 
				
			||||||
 | 
						if (info->is_ac && info->is_dc) {
 | 
				
			||||||
 | 
							sr_dbg("Both AC and DC flags detected in packet.");
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV gboolean sr_vc96_packet_valid(const uint8_t *buf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct vc96_info info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&info, 0x00, sizeof(struct vc96_info));
 | 
				
			||||||
 | 
						parse_flags((const char *)buf, &info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!flags_valid(&info))
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((buf[11] != '\r') || (buf[12] != '\n'))
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Parse a protocol packet.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param buf Buffer containing the protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param floatval Pointer to a float variable. That variable will be modified
 | 
				
			||||||
 | 
					 *                 in-place depending on the protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 * @param analog Pointer to a struct sr_datafeed_analog. The struct will be
 | 
				
			||||||
 | 
					 *               filled with data according to the protocol packet.
 | 
				
			||||||
 | 
					 *               Must not be NULL.
 | 
				
			||||||
 | 
					 * @param info Pointer to a struct vc96_info. The struct will be filled
 | 
				
			||||||
 | 
					 *             with data according to the protocol packet. Must not be NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the
 | 
				
			||||||
 | 
					 *         'analog' variable contents are undefined and should not be used.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					SR_PRIV int sr_vc96_parse(const uint8_t *buf, float *floatval,
 | 
				
			||||||
 | 
								struct sr_datafeed_analog *analog, void *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret, exponent = 0;
 | 
				
			||||||
 | 
						struct vc96_info *info_local;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info_local = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Don't print byte 12 + 13. Those contain the CR LF. */
 | 
				
			||||||
 | 
						sr_dbg("DMM packet: \"%.11s\".", buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(info_local, 0x00, sizeof(struct vc96_info));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((ret = parse_value(buf, info_local, floatval, &exponent)) < 0) {
 | 
				
			||||||
 | 
							sr_dbg("Error parsing value: %d.", ret);
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						parse_flags((const char *)buf, info_local);
 | 
				
			||||||
 | 
						handle_flags(analog, floatval, &exponent, info_local);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						analog->encoding->digits = -exponent;
 | 
				
			||||||
 | 
						analog->spec->spec_digits = -exponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2017 Marcus Comstedt <marcus@mc.pp.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This marks the start of the driver list. This file must be linked
 | 
				
			||||||
 | 
					 * before any actual drivers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const struct sr_dev_driver *sr_driver_list__start[]
 | 
				
			||||||
 | 
						SR_DRIVER_LIST_NOREORDER
 | 
				
			||||||
 | 
						__attribute__((section (SR_DRIVER_LIST_SECTION),
 | 
				
			||||||
 | 
							       used, aligned(sizeof(struct sr_dev_driver *))))
 | 
				
			||||||
 | 
					  = { NULL /* Dummy item, as zero length arrays are not allowed by C99 */ };
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2017 Marcus Comstedt <marcus@mc.pp.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This marks the end of the driver list. This file must be linked
 | 
				
			||||||
 | 
					 * after any actual drivers.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const struct sr_dev_driver *sr_driver_list__stop[]
 | 
				
			||||||
 | 
						SR_DRIVER_LIST_NOREORDER
 | 
				
			||||||
 | 
						__attribute__((section (SR_DRIVER_LIST_SECTION),
 | 
				
			||||||
 | 
							       used, aligned(sizeof(struct sr_dev_driver *))))
 | 
				
			||||||
 | 
					  = { NULL /* Dummy item, as zero length arrays are not allowed by C99 */ };
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2016 Lars-Peter Clausen <lars@metafoo.de>
 | 
					 * Copyright (C) 2016 Lars-Peter Clausen <lars@metafoo.de>
 | 
				
			||||||
 * Copyright (C) 2016 Aurelien Jacobs <aurel@gnuage.org>
 | 
					 * Copyright (C) 2016 Aurelien Jacobs <aurel@gnuage.org>
 | 
				
			||||||
 | 
					 * Copyright (C) 2017 Marcus Comstedt <marcus@mc.pp.se>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -26,22 +27,19 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * sr_driver_list is a special section contains pointers to all the hardware
 | 
					 * sr_driver_list is a special section contains pointers to all the hardware
 | 
				
			||||||
 * drivers built into the library. The __start and __stop symbols are
 | 
					 * drivers built into the library. The __start and __stop symbols are
 | 
				
			||||||
 * auto-generated by the linker (OSX needs a little help) and point to the start
 | 
					 * created from driver_list_start.c and driver_list_stop.c, and point to the
 | 
				
			||||||
 * and end of the section. They are used to iterate over the list of all
 | 
					 * start and end of the section. They are used to iterate over the list of
 | 
				
			||||||
 * drivers.
 | 
					 * all drivers.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifdef __APPLE__
 | 
					SR_PRIV extern const struct sr_dev_driver *sr_driver_list__start[];
 | 
				
			||||||
extern struct sr_dev_driver *__start_sr_driver_list __asm("section$start$__DATA$__sr_driver_list");
 | 
					SR_PRIV extern const struct sr_dev_driver *sr_driver_list__stop[];
 | 
				
			||||||
extern struct sr_dev_driver *__stop_sr_driver_list __asm("section$end$__DATA$__sr_driver_list");
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
extern struct sr_dev_driver *__start_sr_driver_list;
 | 
					 | 
				
			||||||
extern struct sr_dev_driver *__stop_sr_driver_list;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @private
 | 
					/**
 | 
				
			||||||
 * Initialize the driver list in a fresh libsigrok context.
 | 
					 * Initialize the driver list in a fresh libsigrok context.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param ctx Pointer to a libsigrok context struct. Must not be NULL.
 | 
					 * @param ctx Pointer to a libsigrok context struct. Must not be NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @private
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SR_API void sr_drivers_init(struct sr_context *ctx)
 | 
					SR_API void sr_drivers_init(struct sr_context *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -49,8 +47,8 @@ SR_API void sr_drivers_init(struct sr_context *ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	array = g_array_new(TRUE, FALSE, sizeof(struct sr_dev_driver *));
 | 
						array = g_array_new(TRUE, FALSE, sizeof(struct sr_dev_driver *));
 | 
				
			||||||
#ifdef HAVE_DRIVERS
 | 
					#ifdef HAVE_DRIVERS
 | 
				
			||||||
	for (struct sr_dev_driver **drivers = &__start_sr_driver_list;
 | 
						for (const struct sr_dev_driver **drivers = sr_driver_list__start + 1;
 | 
				
			||||||
	     drivers < &__stop_sr_driver_list; drivers++)
 | 
						     drivers < sr_driver_list__stop; drivers++)
 | 
				
			||||||
		g_array_append_val(array, *drivers);
 | 
							g_array_append_val(array, *drivers);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	ctx->driver_list = (struct sr_dev_driver **)array->data;
 | 
						ctx->driver_list = (struct sr_dev_driver **)array->data;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,8 +20,9 @@
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#include <glib.h>
 | 
					#include <glib.h>
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef HAVE_LIBSERIALPORT
 | 
					#ifndef HAVE_SERIAL_COMM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_API GSList *sr_serial_list(const struct sr_dev_driver *driver)
 | 
					SR_API GSList *sr_serial_list(const struct sr_dev_driver *driver)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,11 +51,7 @@ static const uint64_t samplerates[] = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *data_sources[] = {
 | 
					static const char *data_sources[] = {
 | 
				
			||||||
	"Live",
 | 
						"Live", "Log-Hand", "Log-Trig", "Log-Auto", "Log-Export",
 | 
				
			||||||
	"Log-Hand",
 | 
					 | 
				
			||||||
	"Log-Trig",
 | 
					 | 
				
			||||||
	"Log-Auto",
 | 
					 | 
				
			||||||
	"Log-Export",
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const struct agdmm_job agdmm_jobs_live[];
 | 
					extern const struct agdmm_job agdmm_jobs_live[];
 | 
				
			||||||
| 
						 | 
					@ -64,6 +60,7 @@ extern const struct agdmm_recv agdmm_recvs_u123x[];
 | 
				
			||||||
extern const struct agdmm_recv agdmm_recvs_u124x[];
 | 
					extern const struct agdmm_recv agdmm_recvs_u124x[];
 | 
				
			||||||
extern const struct agdmm_recv agdmm_recvs_u124xc[];
 | 
					extern const struct agdmm_recv agdmm_recvs_u124xc[];
 | 
				
			||||||
extern const struct agdmm_recv agdmm_recvs_u125x[];
 | 
					extern const struct agdmm_recv agdmm_recvs_u125x[];
 | 
				
			||||||
 | 
					extern const struct agdmm_recv agdmm_recvs_u127x[];
 | 
				
			||||||
extern const struct agdmm_recv agdmm_recvs_u128x[];
 | 
					extern const struct agdmm_recv agdmm_recvs_u128x[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This works on all the Agilent U12xxA series, although the
 | 
					/* This works on all the Agilent U12xxA series, although the
 | 
				
			||||||
| 
						 | 
					@ -90,6 +87,11 @@ static const struct agdmm_profile supported_agdmm[] = {
 | 
				
			||||||
	{ AGILENT_U1252, "U1252B", 3, agdmm_jobs_live, NULL, agdmm_recvs_u125x },
 | 
						{ AGILENT_U1252, "U1252B", 3, agdmm_jobs_live, NULL, agdmm_recvs_u125x },
 | 
				
			||||||
	{ AGILENT_U1253, "U1253B", 3, agdmm_jobs_live, NULL, agdmm_recvs_u125x },
 | 
						{ AGILENT_U1253, "U1253B", 3, agdmm_jobs_live, NULL, agdmm_recvs_u125x },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{ AGILENT_U1271, "U1271A", 3, agdmm_jobs_live, NULL, agdmm_recvs_u127x },
 | 
				
			||||||
 | 
						{ AGILENT_U1272, "U1272A", 3, agdmm_jobs_live, NULL, agdmm_recvs_u127x },
 | 
				
			||||||
 | 
						{ AGILENT_U1273, "U1273A", 3, agdmm_jobs_live, NULL, agdmm_recvs_u127x },
 | 
				
			||||||
 | 
						{ AGILENT_U1273AX, "U1273AX", 3, agdmm_jobs_live, NULL, agdmm_recvs_u127x },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{ KEYSIGHT_U1281, "U1281A", 3, agdmm_jobs_live, agdmm_jobs_log, agdmm_recvs_u128x },
 | 
						{ KEYSIGHT_U1281, "U1281A", 3, agdmm_jobs_live, agdmm_jobs_log, agdmm_recvs_u128x },
 | 
				
			||||||
	{ KEYSIGHT_U1282, "U1282A", 3, agdmm_jobs_live, agdmm_jobs_log, agdmm_recvs_u128x },
 | 
						{ KEYSIGHT_U1282, "U1282A", 3, agdmm_jobs_live, agdmm_jobs_log, agdmm_recvs_u128x },
 | 
				
			||||||
	ALL_ZERO
 | 
						ALL_ZERO
 | 
				
			||||||
| 
						 | 
					@ -129,7 +131,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
						if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
					 | 
				
			||||||
	if (serial_write_blocking(serial, "*IDN?\r\n", 7, SERIAL_WRITE_TIMEOUT_MS) < 7) {
 | 
						if (serial_write_blocking(serial, "*IDN?\r\n", 7, SERIAL_WRITE_TIMEOUT_MS) < 7) {
 | 
				
			||||||
		sr_err("Unable to send identification string.");
 | 
							sr_err("Unable to send identification string.");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -187,25 +188,22 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	return std_scan_complete(di, devices);
 | 
						return std_scan_complete(di, devices);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->cur_samplerate);
 | 
							*data = g_variant_new_uint64(devc->cur_samplerate);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		ret = sr_sw_limits_config_get(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_get(&devc->limits, key, data);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DATA_SOURCE:
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
		*data = g_variant_new_string(data_sources[devc->data_source]);
 | 
							*data = g_variant_new_string(data_sources[devc->data_source]);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -213,91 +211,54 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	uint64_t samplerate;
 | 
						uint64_t samplerate;
 | 
				
			||||||
	const char *tmp_str;
 | 
						int idx;
 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		samplerate = g_variant_get_uint64(data);
 | 
							samplerate = g_variant_get_uint64(data);
 | 
				
			||||||
		if (samplerate < samplerates[0] || samplerate > samplerates[1])
 | 
							if (samplerate < samplerates[0] || samplerate > samplerates[1])
 | 
				
			||||||
			ret = SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		devc->cur_samplerate = g_variant_get_uint64(data);
 | 
							devc->cur_samplerate = g_variant_get_uint64(data);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		ret = sr_sw_limits_config_set(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
				
			||||||
		break;
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
	case SR_CONF_DATA_SOURCE: {
 | 
							if ((idx = std_str_idx(data, ARRAY_AND_SIZE(data_sources))) < 0)
 | 
				
			||||||
		tmp_str = g_variant_get_string(data, NULL);
 | 
					 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(data_sources); i++)
 | 
					 | 
				
			||||||
			if (!strcmp(tmp_str, data_sources[i])) {
 | 
					 | 
				
			||||||
				devc->data_source = i;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		if (i == ARRAY_SIZE(data_sources))
 | 
					 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	GVariant *gvar;
 | 
					 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (key == SR_CONF_SCAN_OPTIONS) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sdi || cg)
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
 | 
							devc->data_source = idx;
 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return SR_ERR_NA;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (key) {
 | 
				
			||||||
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
 | 
							*data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
 | 
				
			||||||
		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
 | 
					 | 
				
			||||||
				ARRAY_SIZE(samplerates), sizeof(uint64_t));
 | 
					 | 
				
			||||||
		g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
 | 
					 | 
				
			||||||
		*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_DATA_SOURCE:
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
		*data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
| 
						 | 
					@ -311,9 +272,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc->cur_channel = sr_next_enabled_channel(sdi, NULL);
 | 
						devc->cur_channel = sr_next_enabled_channel(sdi, NULL);
 | 
				
			||||||
	devc->cur_conf = sr_next_enabled_channel(sdi, NULL);
 | 
						devc->cur_conf = sr_next_enabled_channel(sdi, NULL);
 | 
				
			||||||
	devc->cur_sample = 1;
 | 
						devc->cur_sample = 1;
 | 
				
			||||||
| 
						 | 
					@ -338,7 +296,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->limits);
 | 
						sr_sw_limits_acquisition_start(&devc->limits);
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 10ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 10,
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 10,
 | 
				
			||||||
			agdmm_receive_data, (void *)sdi);
 | 
								agdmm_receive_data, (void *)sdi);
 | 
				
			||||||
| 
						 | 
					@ -354,7 +311,7 @@ static struct sr_dev_driver agdmm_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ SR_PRIV int agdmm_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->limits) || stop)
 | 
						if (sr_sw_limits_check(&devc->limits) || stop)
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		dispatch(sdi);
 | 
							dispatch(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -574,6 +574,12 @@ static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
 | 
				
			||||||
		devc->cur_mqflags[i] = 0;
 | 
							devc->cur_mqflags[i] = 0;
 | 
				
			||||||
		devc->cur_exponent[i] = 0;
 | 
							devc->cur_exponent[i] = 0;
 | 
				
			||||||
		devc->cur_digits[i] = 3 - resolution;
 | 
							devc->cur_digits[i] = 3 - resolution;
 | 
				
			||||||
 | 
						} else if (!strcmp(mstr, "MA")) {
 | 
				
			||||||
 | 
							devc->cur_mq[i] = SR_MQ_CURRENT;
 | 
				
			||||||
 | 
							devc->cur_unit[i] = SR_UNIT_AMPERE;
 | 
				
			||||||
 | 
							devc->cur_mqflags[i] = 0;
 | 
				
			||||||
 | 
							devc->cur_exponent[i] = -3;
 | 
				
			||||||
 | 
							devc->cur_digits[i] = 8 - resolution;
 | 
				
			||||||
	} else if (!strcmp(mstr, "UA")) {
 | 
						} else if (!strcmp(mstr, "UA")) {
 | 
				
			||||||
		devc->cur_mq[i] = SR_MQ_CURRENT;
 | 
							devc->cur_mq[i] = SR_MQ_CURRENT;
 | 
				
			||||||
		devc->cur_unit[i] = SR_UNIT_AMPERE;
 | 
							devc->cur_unit[i] = SR_UNIT_AMPERE;
 | 
				
			||||||
| 
						 | 
					@ -600,9 +606,15 @@ static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
 | 
				
			||||||
	} else if (!strcmp(mstr, "DIOD")) {
 | 
						} else if (!strcmp(mstr, "DIOD")) {
 | 
				
			||||||
		devc->cur_mq[i] = SR_MQ_VOLTAGE;
 | 
							devc->cur_mq[i] = SR_MQ_VOLTAGE;
 | 
				
			||||||
		devc->cur_unit[i] = SR_UNIT_VOLT;
 | 
							devc->cur_unit[i] = SR_UNIT_VOLT;
 | 
				
			||||||
		devc->cur_mqflags[i] = SR_MQFLAG_DIODE;
 | 
							devc->cur_mqflags[i] = SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
		devc->cur_exponent[i] = 0;
 | 
							devc->cur_exponent[i] = 0;
 | 
				
			||||||
		devc->cur_digits[i] = 3;
 | 
							devc->cur_digits[i] = 3;
 | 
				
			||||||
 | 
						} else if (!strcmp(mstr, "TEMP")) {
 | 
				
			||||||
 | 
							devc->cur_mq[i] = SR_MQ_TEMPERATURE;
 | 
				
			||||||
 | 
							devc->cur_unit[i] = SR_UNIT_CELSIUS;
 | 
				
			||||||
 | 
							devc->cur_mqflags[i] = 0;
 | 
				
			||||||
 | 
							devc->cur_exponent[i] = 0;
 | 
				
			||||||
 | 
							devc->cur_digits[i] = 1;
 | 
				
			||||||
	} else if (!strcmp(mstr, "CAP")) {
 | 
						} else if (!strcmp(mstr, "CAP")) {
 | 
				
			||||||
		devc->cur_mq[i] = SR_MQ_CAPACITANCE;
 | 
							devc->cur_mq[i] = SR_MQ_CAPACITANCE;
 | 
				
			||||||
		devc->cur_unit[i] = SR_UNIT_FARAD;
 | 
							devc->cur_unit[i] = SR_UNIT_FARAD;
 | 
				
			||||||
| 
						 | 
					@ -625,6 +637,8 @@ static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
 | 
				
			||||||
				devc->cur_mqflags[i] |= SR_MQFLAG_RMS;
 | 
									devc->cur_mqflags[i] |= SR_MQFLAG_RMS;
 | 
				
			||||||
		} else if (!strcmp(mstr, "DC")) {
 | 
							} else if (!strcmp(mstr, "DC")) {
 | 
				
			||||||
			devc->cur_mqflags[i] |= SR_MQFLAG_DC;
 | 
								devc->cur_mqflags[i] |= SR_MQFLAG_DC;
 | 
				
			||||||
 | 
							} else if (!strcmp(mstr, "ACDC")) {
 | 
				
			||||||
 | 
								devc->cur_mqflags[i] |= SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			sr_dbg("Unknown first argument '%s'.", mstr);
 | 
								sr_dbg("Unknown first argument '%s'.", mstr);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -632,6 +646,13 @@ static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		devc->cur_mqflags[i] &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
 | 
							devc->cur_mqflags[i] &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sr_channel *prev_conf = devc->cur_conf;
 | 
				
			||||||
 | 
						devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
 | 
				
			||||||
 | 
						if (devc->cur_conf->index >= MIN(devc->profile->nb_channels, 2))
 | 
				
			||||||
 | 
							devc->cur_conf = sr_next_enabled_channel(sdi, devc->cur_conf);
 | 
				
			||||||
 | 
						if (devc->cur_conf->index > prev_conf->index)
 | 
				
			||||||
 | 
							return JOB_AGAIN;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		return JOB_CONF;
 | 
							return JOB_CONF;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -738,7 +759,7 @@ static int recv_conf_u124x_5x(const struct sr_dev_inst *sdi, GMatchInfo *match)
 | 
				
			||||||
	} else if (!strcmp(mstr, "DIOD")) {
 | 
						} else if (!strcmp(mstr, "DIOD")) {
 | 
				
			||||||
		devc->cur_mq[i] = SR_MQ_VOLTAGE;
 | 
							devc->cur_mq[i] = SR_MQ_VOLTAGE;
 | 
				
			||||||
		devc->cur_unit[i] = SR_UNIT_VOLT;
 | 
							devc->cur_unit[i] = SR_UNIT_VOLT;
 | 
				
			||||||
		devc->cur_mqflags[i] = SR_MQFLAG_DIODE;
 | 
							devc->cur_mqflags[i] = SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
		devc->cur_exponent[i] = 0;
 | 
							devc->cur_exponent[i] = 0;
 | 
				
			||||||
		if (devc->profile->model == KEYSIGHT_U1281 ||
 | 
							if (devc->profile->model == KEYSIGHT_U1281 ||
 | 
				
			||||||
		    devc->profile->model == KEYSIGHT_U1282) {
 | 
							    devc->profile->model == KEYSIGHT_U1282) {
 | 
				
			||||||
| 
						 | 
					@ -871,7 +892,7 @@ static int recv_log(const struct sr_dev_inst *sdi, GMatchInfo *match,
 | 
				
			||||||
	if (mstr[12] & 1)  mqflags |= SR_MQFLAG_AVG;
 | 
						if (mstr[12] & 1)  mqflags |= SR_MQFLAG_AVG;
 | 
				
			||||||
	if (mstr[12] & 2)  mqflags |= SR_MQFLAG_MIN;
 | 
						if (mstr[12] & 2)  mqflags |= SR_MQFLAG_MIN;
 | 
				
			||||||
	if (mstr[12] & 4)  mqflags |= SR_MQFLAG_MAX;
 | 
						if (mstr[12] & 4)  mqflags |= SR_MQFLAG_MAX;
 | 
				
			||||||
	if (function == 5) mqflags |= SR_MQFLAG_DIODE;
 | 
						if (function == 5) mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
 | 
				
			||||||
	g_free(mstr);
 | 
						g_free(mstr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mq = mqs[function];
 | 
						mq = mqs[function];
 | 
				
			||||||
| 
						 | 
					@ -1017,12 +1038,24 @@ SR_PRIV const struct agdmm_recv agdmm_recvs_u125x[] = {
 | 
				
			||||||
	{ "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u125x },
 | 
						{ "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u125x },
 | 
				
			||||||
	{ "^\\*([0-9])$", recv_switch },
 | 
						{ "^\\*([0-9])$", recv_switch },
 | 
				
			||||||
	{ "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
 | 
						{ "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
 | 
				
			||||||
	{ "^\"(VOLT|CURR|RES|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(VOLT|CURR|RES|CONT|COND|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
				
			||||||
	{ "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
				
			||||||
	{ "^\"(CURR:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(CURR:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
				
			||||||
	{ "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{8}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
				
			||||||
 | 
						{ "^\"(PULS:PWID|PULS:PWID:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9]\\.[0-9]{6}E([-+][0-9]{2}))\"$", recv_conf_u124x_5x },
 | 
				
			||||||
 | 
						{ "^\"(TEMP:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
 | 
				
			||||||
	{ "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
 | 
				
			||||||
	{ "^\"(DIOD)\"$", recv_conf_u124x_5x },
 | 
						{ "^\"(DIOD|PULS:[PN]DUT)\"$", recv_conf_u124x_5x },
 | 
				
			||||||
 | 
						ALL_ZERO
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const struct agdmm_recv agdmm_recvs_u127x[] = {
 | 
				
			||||||
 | 
						{ "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u123x },
 | 
				
			||||||
 | 
						{ "^\\*([0-9]+)$", recv_switch },
 | 
				
			||||||
 | 
						{ "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
 | 
				
			||||||
 | 
						{ "^\"(V|MV|A|MA|UA|FREQ),(\\d),(AC|DC|ACDC)\"$", recv_conf_u123x },
 | 
				
			||||||
 | 
						{ "^\"(RES|CAP),(\\d)\"$", recv_conf_u123x},
 | 
				
			||||||
 | 
						{ "^\"(DIOD|TEMP)\"$", recv_conf_u123x },
 | 
				
			||||||
	ALL_ZERO
 | 
						ALL_ZERO
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,11 @@ enum {
 | 
				
			||||||
	AGILENT_U1252,
 | 
						AGILENT_U1252,
 | 
				
			||||||
	AGILENT_U1253,
 | 
						AGILENT_U1253,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						AGILENT_U1271,
 | 
				
			||||||
 | 
						AGILENT_U1272,
 | 
				
			||||||
 | 
						AGILENT_U1273,
 | 
				
			||||||
 | 
						AGILENT_U1273AX,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	KEYSIGHT_U1281,
 | 
						KEYSIGHT_U1281,
 | 
				
			||||||
	KEYSIGHT_U1282,
 | 
						KEYSIGHT_U1282,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -68,13 +73,11 @@ struct agdmm_profile {
 | 
				
			||||||
	const struct agdmm_recv *recvs;
 | 
						const struct agdmm_recv *recvs;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	const struct agdmm_profile *profile;
 | 
						const struct agdmm_profile *profile;
 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
						struct sr_sw_limits limits;
 | 
				
			||||||
	int data_source;
 | 
						int data_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Runtime. */
 | 
					 | 
				
			||||||
	const struct agdmm_job *jobs;
 | 
						const struct agdmm_job *jobs;
 | 
				
			||||||
	int current_job;
 | 
						int current_job;
 | 
				
			||||||
	gboolean job_running;
 | 
						gboolean job_running;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,11 +79,9 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_info("Probing serial port %s.", conn);
 | 
						sr_info("Probing serial port %s.", conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Let's get a bit of data and see if we can find a packet. */
 | 
						/* Let's get a bit of data and see if we can find a packet. */
 | 
				
			||||||
	if (serial_stream_detect(serial, buf, &len, 25,
 | 
						if (serial_stream_detect(serial, buf, &len, 25,
 | 
				
			||||||
			appa_55ii_packet_valid, 500, 9600) != SR_OK)
 | 
								appa_55ii_packet_valid, NULL, NULL, 500) != SR_OK)
 | 
				
			||||||
		goto scan_cleanup;
 | 
							goto scan_cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_info("Found device on port %s.", conn);
 | 
						sr_info("Found device on port %s.", conn);
 | 
				
			||||||
| 
						 | 
					@ -109,8 +107,8 @@ scan_cleanup:
 | 
				
			||||||
	return std_scan_complete(di, devices);
 | 
						return std_scan_complete(di, devices);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,35 +128,25 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	const char *tmp_str;
 | 
						int idx;
 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
				
			||||||
	case SR_CONF_DATA_SOURCE: {
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
		tmp_str = g_variant_get_string(data, NULL);
 | 
							if ((idx = std_str_idx(data, ARRAY_AND_SIZE(data_sources))) < 0)
 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(data_sources); i++)
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
			if (!strcmp(tmp_str, data_sources[i])) {
 | 
							devc->data_source = idx;
 | 
				
			||||||
				devc->data_source = i;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		if (i == ARRAY_SIZE(data_sources))
 | 
					 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -166,26 +154,15 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
		if (!sdi)
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DATA_SOURCE:
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
		*data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
| 
						 | 
					@ -200,16 +177,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->limits);
 | 
						sr_sw_limits_acquisition_start(&devc->limits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 50ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 50,
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 50,
 | 
				
			||||||
			appa_55ii_receive_data, (void *)sdi);
 | 
								appa_55ii_receive_data, (void *)sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,7 +197,7 @@ static struct sr_dev_driver appa_55ii_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -224,7 +224,7 @@ static void appa_55ii_log_end(struct sr_dev_inst *sdi)
 | 
				
			||||||
	if (devc->data_source != DATA_SOURCE_MEMORY)
 | 
						if (devc->data_source != DATA_SOURCE_MEMORY)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi->driver->dev_acquisition_stop(sdi);
 | 
						sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint8_t *appa_55ii_parse_data(struct sr_dev_inst *sdi,
 | 
					static const uint8_t *appa_55ii_parse_data(struct sr_dev_inst *sdi,
 | 
				
			||||||
| 
						 | 
					@ -309,7 +309,7 @@ SR_PRIV int appa_55ii_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->limits)) {
 | 
						if (sr_sw_limits_check(&devc->limits)) {
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,13 +36,10 @@ enum {
 | 
				
			||||||
	DATA_SOURCE_MEMORY,
 | 
						DATA_SOURCE_MEMORY,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	/* Acquisition settings */
 | 
					 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
						struct sr_sw_limits limits;
 | 
				
			||||||
	gboolean data_source; /**< Whether to read live samples or memory */
 | 
						gboolean data_source; /**< Whether to read live samples or memory */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Temporary state across callbacks */
 | 
					 | 
				
			||||||
	uint8_t buf[APPA_55II_BUF_SIZE];
 | 
						uint8_t buf[APPA_55II_BUF_SIZE];
 | 
				
			||||||
	unsigned int buf_len;
 | 
						unsigned int buf_len;
 | 
				
			||||||
	uint8_t log_buf[64];
 | 
						uint8_t log_buf[64];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CMD_VERSION "version\r\n"
 | 
					#define CMD_VERSION "version\r\n"
 | 
				
			||||||
#define CMD_MONITOR "monitor 200\r\n"
 | 
					#define CMD_MONITOR "monitor 200\r\n"
 | 
				
			||||||
 | 
					#define CMD_MONITOR_STOP "monitor 0\r\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t scanopts[] = {
 | 
					static const uint32_t scanopts[] = {
 | 
				
			||||||
	SR_CONF_CONN,
 | 
						SR_CONF_CONN,
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,7 @@ static const uint32_t devopts[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t devopts_cg[] = {
 | 
					static const uint32_t devopts_cg[] = {
 | 
				
			||||||
	SR_CONF_ENABLED | SR_CONF_SET,
 | 
						SR_CONF_ENABLED | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_REGULATION | SR_CONF_GET,
 | 
						SR_CONF_REGULATION | SR_CONF_GET | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_VOLTAGE | SR_CONF_GET,
 | 
						SR_CONF_VOLTAGE | SR_CONF_GET,
 | 
				
			||||||
	SR_CONF_CURRENT | SR_CONF_GET,
 | 
						SR_CONF_CURRENT | SR_CONF_GET,
 | 
				
			||||||
	SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
						SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
| 
						 | 
					@ -53,6 +54,12 @@ static const uint32_t devopts_cg[] = {
 | 
				
			||||||
	SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE | SR_CONF_GET,
 | 
						SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE | SR_CONF_GET,
 | 
				
			||||||
	SR_CONF_UNDER_VOLTAGE_CONDITION | SR_CONF_GET,
 | 
						SR_CONF_UNDER_VOLTAGE_CONDITION | SR_CONF_GET,
 | 
				
			||||||
	SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE | SR_CONF_GET,
 | 
						SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE | SR_CONF_GET,
 | 
				
			||||||
 | 
						SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *regulation[] = {
 | 
				
			||||||
 | 
						/* CC mode only. */
 | 
				
			||||||
 | 
						"CC",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
| 
						 | 
					@ -92,7 +99,18 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
						if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
						/*
 | 
				
			||||||
 | 
						 * First stop potentially running monitoring and wait for 50ms before
 | 
				
			||||||
 | 
						 * next command can be sent.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (serial_write_blocking(serial, CMD_MONITOR_STOP,
 | 
				
			||||||
 | 
								strlen(CMD_MONITOR_STOP), serial_timeout(serial,
 | 
				
			||||||
 | 
								strlen(CMD_MONITOR_STOP))) < (int)strlen(CMD_MONITOR_STOP)) {
 | 
				
			||||||
 | 
							sr_dbg("Unable to write while probing for hardware.");
 | 
				
			||||||
 | 
							serial_close(serial);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g_usleep(50 * 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (serial_write_blocking(serial, CMD_VERSION,
 | 
						if (serial_write_blocking(serial, CMD_VERSION,
 | 
				
			||||||
			strlen(CMD_VERSION), serial_timeout(serial,
 | 
								strlen(CMD_VERSION), serial_timeout(serial,
 | 
				
			||||||
| 
						 | 
					@ -135,7 +153,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V");
 | 
						ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V");
 | 
				
			||||||
	cg->channels = g_slist_append(cg->channels, ch);
 | 
						cg->channels = g_slist_append(cg->channels, ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ch = sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "I");
 | 
						ch = sr_channel_new(sdi, 1, SR_CHANNEL_ANALOG, TRUE, "I");
 | 
				
			||||||
	cg->channels = g_slist_append(cg->channels, ch);
 | 
						cg->channels = g_slist_append(cg->channels, ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = g_malloc0(sizeof(struct dev_context));
 | 
						devc = g_malloc0(sizeof(struct dev_context));
 | 
				
			||||||
| 
						 | 
					@ -150,64 +168,34 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Always available. */
 | 
					 | 
				
			||||||
	if (key == SR_CONF_SCAN_OPTIONS) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
			scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
			drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sdi)
 | 
					 | 
				
			||||||
		return SR_ERR_ARG;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!cg) {
 | 
						if (!cg) {
 | 
				
			||||||
		/* No channel group: global options. */
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
		switch (key) {
 | 
					 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return SR_ERR_NA;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
							case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								*data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg));
 | 
				
			||||||
				devopts_cg, ARRAY_SIZE(devopts_cg), sizeof(uint32_t));
 | 
								break;
 | 
				
			||||||
 | 
							case SR_CONF_REGULATION:
 | 
				
			||||||
 | 
								*data = std_gvar_array_str(ARRAY_AND_SIZE(regulation));
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_CURRENT_LIMIT:
 | 
							case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
 | 
								*data = std_gvar_min_max_step(0.0, 6.0, 0.001);
 | 
				
			||||||
			/* Min, max, step. */
 | 
								break;
 | 
				
			||||||
			g_variant_builder_add_value(&gvb, g_variant_new_double(0.0));
 | 
							case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
 | 
				
			||||||
			g_variant_builder_add_value(&gvb, g_variant_new_double(6.0));
 | 
								*data = std_gvar_min_max_step(0.0, 60.0, 0.001);
 | 
				
			||||||
			g_variant_builder_add_value(&gvb, g_variant_new_double(0.001)); /* 1mA steps */
 | 
					 | 
				
			||||||
			*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	float fvalue;
 | 
						float fvalue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
| 
						 | 
					@ -223,7 +211,6 @@ static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
	 *  - SR_CONF_ENABLED (state cannot be queried, only set)
 | 
						 *  - SR_CONF_ENABLED (state cannot be queried, only set)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
| 
						 | 
					@ -258,48 +245,59 @@ static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		*data = g_variant_new_boolean(devc->otp_active);
 | 
							*data = g_variant_new_boolean(devc->otp_active);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_UNDER_VOLTAGE_CONDITION:
 | 
						case SR_CONF_UNDER_VOLTAGE_CONDITION:
 | 
				
			||||||
		*data = g_variant_new_boolean(TRUE); /* Always on. */
 | 
							if (reloadpro_get_under_voltage_threshold(sdi, &fvalue) == SR_OK)
 | 
				
			||||||
 | 
								*data = g_variant_new_boolean(fvalue != 0.0);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE:
 | 
						case SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE:
 | 
				
			||||||
		*data = g_variant_new_boolean(devc->uvc_active);
 | 
							*data = g_variant_new_boolean(devc->uvc_active);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
 | 
				
			||||||
 | 
							if (reloadpro_get_under_voltage_threshold(sdi, &fvalue) == SR_OK)
 | 
				
			||||||
 | 
								*data = g_variant_new_double(fvalue);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
				
			||||||
	case SR_CONF_ENABLED:
 | 
						case SR_CONF_ENABLED:
 | 
				
			||||||
		ret = reloadpro_set_on_off(sdi, g_variant_get_boolean(data));
 | 
							return reloadpro_set_on_off(sdi, g_variant_get_boolean(data));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_CURRENT_LIMIT:
 | 
						case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
		ret = reloadpro_set_current_limit(sdi,
 | 
							return reloadpro_set_current_limit(sdi, g_variant_get_double(data));
 | 
				
			||||||
 | 
						case SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD:
 | 
				
			||||||
 | 
							return reloadpro_set_under_voltage_threshold(sdi,
 | 
				
			||||||
			g_variant_get_double(data));
 | 
								g_variant_get_double(data));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (serial_write_blocking(sdi->conn, CMD_MONITOR_STOP,
 | 
				
			||||||
 | 
								strlen(CMD_MONITOR_STOP), serial_timeout(sdi->conn,
 | 
				
			||||||
 | 
								strlen(CMD_MONITOR_STOP))) < (int)strlen(CMD_MONITOR_STOP)) {
 | 
				
			||||||
 | 
							sr_dbg("Unable to stop monitoring.");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return std_serial_dev_close(sdi);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -308,10 +306,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
						devc->acquisition_running = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Send the 'monitor <ms>' command (doesn't have a reply). */
 | 
						/* Send the 'monitor <ms>' command (doesn't have a reply). */
 | 
				
			||||||
| 
						 | 
					@ -322,19 +319,34 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 100ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 100,
 | 
					 | 
				
			||||||
			  reloadpro_receive_data, (void *)sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->limits);
 | 
						sr_sw_limits_acquisition_start(&devc->limits);
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(devc->buf, 0, RELOADPRO_BUFSIZE);
 | 
						memset(devc->buf, 0, RELOADPRO_BUFSIZE);
 | 
				
			||||||
	devc->buflen = 0;
 | 
						devc->buflen = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_mutex_init(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 100,
 | 
				
			||||||
 | 
								  reloadpro_receive_data, (void *)sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
						devc->acquisition_running = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = std_serial_dev_acquisition_stop(sdi);
 | 
				
			||||||
 | 
						g_mutex_clear(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct sr_dev_driver arachnid_labs_re_load_pro_driver_info = {
 | 
					static struct sr_dev_driver arachnid_labs_re_load_pro_driver_info = {
 | 
				
			||||||
	.name = "arachnid-labs-re-load-pro",
 | 
						.name = "arachnid-labs-re-load-pro",
 | 
				
			||||||
	.longname = "Arachnid Labs Re:load Pro",
 | 
						.longname = "Arachnid Labs Re:load Pro",
 | 
				
			||||||
| 
						 | 
					@ -343,13 +355,14 @@ static struct sr_dev_driver arachnid_labs_re_load_pro_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
	.dev_open = std_serial_dev_open,
 | 
						.dev_open = std_serial_dev_open,
 | 
				
			||||||
	.dev_close = std_serial_dev_close,
 | 
						.dev_close = dev_close,
 | 
				
			||||||
	.dev_acquisition_start = dev_acquisition_start,
 | 
						.dev_acquisition_start = dev_acquisition_start,
 | 
				
			||||||
	.dev_acquisition_stop = std_serial_dev_acquisition_stop,
 | 
						.dev_acquisition_stop = dev_acquisition_stop,
 | 
				
			||||||
	.context = NULL,
 | 
						.context = NULL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
SR_REGISTER_DEV_DRIVER(arachnid_labs_re_load_pro_driver_info);
 | 
					SR_REGISTER_DEV_DRIVER(arachnid_labs_re_load_pro_driver_info);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,18 +18,21 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define READ_TIMEOUT_MS 1000
 | 
					#define READ_TIMEOUT_MS 500
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int send_cmd(const struct sr_dev_inst *sdi, const char *cmd,
 | 
					static int send_cmd(const struct sr_dev_inst *sdi, const char *cmd,
 | 
				
			||||||
		char *replybuf, int replybufsize)
 | 
							char *replybuf, int replybufsize)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *bufptr;
 | 
						char *bufptr;
 | 
				
			||||||
	int len, ret;
 | 
						int len, ret;
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Send the command (blocking, with timeout). */
 | 
						/* Send the command (blocking, with timeout). */
 | 
				
			||||||
| 
						 | 
					@ -40,6 +43,7 @@ static int send_cmd(const struct sr_dev_inst *sdi, const char *cmd,
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!devc->acquisition_running) {
 | 
				
			||||||
		/* Read the reply (blocking, with timeout). */
 | 
							/* Read the reply (blocking, with timeout). */
 | 
				
			||||||
		memset(replybuf, 0, replybufsize);
 | 
							memset(replybuf, 0, replybufsize);
 | 
				
			||||||
		bufptr = replybuf;
 | 
							bufptr = replybuf;
 | 
				
			||||||
| 
						 | 
					@ -56,66 +60,165 @@ static int send_cmd(const struct sr_dev_inst *sdi, const char *cmd,
 | 
				
			||||||
			sr_err("Device replied with an error: '%s'.", bufptr);
 | 
								sr_err("Device replied with an error: '%s'.", bufptr);
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int reloadpro_set_current_limit(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_set_current_limit(const struct sr_dev_inst *sdi,
 | 
				
			||||||
					float current)
 | 
										float current_limit)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret, ma;
 | 
						int ret, ma;
 | 
				
			||||||
	char buf[100];
 | 
						char buf[100];
 | 
				
			||||||
	char *cmd;
 | 
						char *cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (current < 0 || current > 6) {
 | 
						devc = sdi->priv;
 | 
				
			||||||
		sr_err("The current limit must be 0-6 A (was %f A).", current);
 | 
					
 | 
				
			||||||
 | 
						if (current_limit < 0 || current_limit > 6) {
 | 
				
			||||||
 | 
							sr_err("The current limit must be 0-6 A (was %f A).", current_limit);
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hardware expects current in mA, integer (0..6000). */
 | 
						/* Hardware expects current limit in mA, integer (0..6000). */
 | 
				
			||||||
	ma = (int)(current * 1000);
 | 
						ma = (int)round(current_limit * 1000);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_err("Setting current limit to %f A (%d mA).", current, ma);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd = g_strdup_printf("set %d\n", ma);
 | 
						cmd = g_strdup_printf("set %d\n", ma);
 | 
				
			||||||
	if ((ret = send_cmd(sdi, cmd, (char *)&buf, sizeof(buf))) < 0) {
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
		sr_err("Error sending current limit command: %d.", ret);
 | 
						ret = send_cmd(sdi, cmd, (char *)&buf, sizeof(buf));
 | 
				
			||||||
		g_free(cmd);
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	g_free(cmd);
 | 
						g_free(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							sr_err("Error sending current limit command: %d.", ret);
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int reloadpro_set_on_off(const struct sr_dev_inst *sdi, gboolean on)
 | 
					SR_PRIV int reloadpro_set_on_off(const struct sr_dev_inst *sdi, gboolean on)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	char buf[100];
 | 
						char buf[100];
 | 
				
			||||||
	const char *cmd;
 | 
						const char *cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd = (on) ? "on\n" : "off\n";
 | 
						cmd = (on) ? "on\n" : "off\n";
 | 
				
			||||||
	if ((ret = send_cmd(sdi, cmd, (char *)&buf, sizeof(buf))) < 0) {
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
						ret = send_cmd(sdi, cmd, (char *)&buf, sizeof(buf));
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
		sr_err("Error sending on/off command: %d.", ret);
 | 
							sr_err("Error sending on/off command: %d.", ret);
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int reloadpro_set_under_voltage_threshold(const struct sr_dev_inst *sdi,
 | 
				
			||||||
 | 
										float voltage)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						int ret, mv;
 | 
				
			||||||
 | 
						char buf[100];
 | 
				
			||||||
 | 
						char *cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (voltage < 0 || voltage > 60) {
 | 
				
			||||||
 | 
							sr_err("The under voltage threshold must be 0-60 V (was %f V).",
 | 
				
			||||||
 | 
								voltage);
 | 
				
			||||||
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Hardware expects voltage in mV, integer (0..60000). */
 | 
				
			||||||
 | 
						mv = (int)round(voltage * 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("Setting under voltage threshold to %f V (%d mV).", voltage, mv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd = g_strdup_printf("uvlo %d\n", mv);
 | 
				
			||||||
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
						ret = send_cmd(sdi, cmd, (char *)&buf, sizeof(buf));
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
						g_free(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret < 0) {
 | 
				
			||||||
 | 
							sr_err("Error sending under voltage threshold command: %d.", ret);
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int reloadpro_get_current_limit(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_get_current_limit(const struct sr_dev_inst *sdi,
 | 
				
			||||||
					float *current)
 | 
										float *current_limit)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	char buf[100];
 | 
						char buf[100];
 | 
				
			||||||
 | 
						gint64 end_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
	if ((ret = send_cmd(sdi, "set\n", (char *)&buf, sizeof(buf))) < 0) {
 | 
						if ((ret = send_cmd(sdi, "set\n", (char *)&buf, sizeof(buf))) < 0) {
 | 
				
			||||||
		sr_err("Error sending current limit query: %d.", ret);
 | 
							sr_err("Error sending current limit query: %d.", ret);
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Hardware sends current in mA, integer (0..6000). */
 | 
						if (devc->acquisition_running) {
 | 
				
			||||||
	*current = g_ascii_strtod(buf + 4, NULL) / 1000;
 | 
							end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
 | 
				
			||||||
 | 
							if (!g_cond_wait_until(&devc->current_limit_cond,
 | 
				
			||||||
 | 
									&devc->acquisition_mutex, end_time)) {
 | 
				
			||||||
 | 
								/* Timeout has passed. */
 | 
				
			||||||
 | 
								g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Hardware sends current limit in mA, integer (0..6000). */
 | 
				
			||||||
 | 
							devc->current_limit = g_ascii_strtod(buf + 4, NULL) / 1000;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (current_limit)
 | 
				
			||||||
 | 
							*current_limit = devc->current_limit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int reloadpro_get_under_voltage_threshold(const struct sr_dev_inst *sdi,
 | 
				
			||||||
 | 
										float *uvc_threshold)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char buf[100];
 | 
				
			||||||
 | 
						gint64 end_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
						if ((ret = send_cmd(sdi, "uvlo\n", (char *)&buf, sizeof(buf))) < 0) {
 | 
				
			||||||
 | 
							sr_err("Error sending under voltage threshold query: %d.", ret);
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (devc->acquisition_running) {
 | 
				
			||||||
 | 
							end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
 | 
				
			||||||
 | 
							if (!g_cond_wait_until(&devc->uvc_threshold_cond,
 | 
				
			||||||
 | 
									&devc->acquisition_mutex, end_time)) {
 | 
				
			||||||
 | 
								/* Timeout has passed. */
 | 
				
			||||||
 | 
								g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/* Hardware sends voltage in mV, integer (0..60000). */
 | 
				
			||||||
 | 
							devc->uvc_threshold = g_ascii_strtod(buf + 5, NULL) / 1000;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (uvc_threshold)
 | 
				
			||||||
 | 
							*uvc_threshold = devc->uvc_threshold;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -123,29 +226,47 @@ SR_PRIV int reloadpro_get_current_limit(const struct sr_dev_inst *sdi,
 | 
				
			||||||
SR_PRIV int reloadpro_get_voltage_current(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_get_voltage_current(const struct sr_dev_inst *sdi,
 | 
				
			||||||
		float *voltage, float *current)
 | 
							float *voltage, float *current)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	char buf[100];
 | 
						char buf[100];
 | 
				
			||||||
	char **tokens;
 | 
						char **tokens;
 | 
				
			||||||
 | 
						gint64 end_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
	if ((ret = send_cmd(sdi, "read\n", (char *)&buf, sizeof(buf))) < 0) {
 | 
						if ((ret = send_cmd(sdi, "read\n", (char *)&buf, sizeof(buf))) < 0) {
 | 
				
			||||||
		sr_err("Error sending voltage/current query: %d.", ret);
 | 
							sr_err("Error sending voltage/current query: %d.", ret);
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (devc->acquisition_running) {
 | 
				
			||||||
 | 
							end_time = g_get_monotonic_time () + 5 * G_TIME_SPAN_SECOND;
 | 
				
			||||||
 | 
							if (!g_cond_wait_until(&devc->voltage_cond,
 | 
				
			||||||
 | 
									&devc->acquisition_mutex, end_time)) {
 | 
				
			||||||
 | 
								/* Timeout has passed. */
 | 
				
			||||||
 | 
								g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		/* Reply: "read <current> <voltage>". */
 | 
							/* Reply: "read <current> <voltage>". */
 | 
				
			||||||
		tokens = g_strsplit((const char *)&buf, " ", 3);
 | 
							tokens = g_strsplit((const char *)&buf, " ", 3);
 | 
				
			||||||
	if (voltage)
 | 
							devc->voltage = g_ascii_strtod(tokens[2], NULL) / 1000;
 | 
				
			||||||
		*voltage = g_ascii_strtod(tokens[2], NULL) / 1000;
 | 
							devc->current = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
				
			||||||
	if (current)
 | 
					 | 
				
			||||||
		*current = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
					 | 
				
			||||||
		g_strfreev(tokens);
 | 
							g_strfreev(tokens);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (voltage)
 | 
				
			||||||
 | 
							*voltage = devc->voltage;
 | 
				
			||||||
 | 
						if (current)
 | 
				
			||||||
 | 
							*current = devc->current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_packet(const struct sr_dev_inst *sdi)
 | 
					static void handle_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	float voltage, current;
 | 
					 | 
				
			||||||
	struct sr_datafeed_packet packet;
 | 
						struct sr_datafeed_packet packet;
 | 
				
			||||||
	struct sr_datafeed_analog analog;
 | 
						struct sr_datafeed_analog analog;
 | 
				
			||||||
	struct sr_analog_encoding encoding;
 | 
						struct sr_analog_encoding encoding;
 | 
				
			||||||
| 
						 | 
					@ -160,12 +281,49 @@ static void handle_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	if (g_str_has_prefix((const char *)devc->buf, "overtemp")) {
 | 
						if (g_str_has_prefix((const char *)devc->buf, "overtemp")) {
 | 
				
			||||||
		sr_warn("Overtemperature condition!");
 | 
							sr_warn("Overtemperature condition!");
 | 
				
			||||||
		devc->otp_active = TRUE;
 | 
							devc->otp_active = TRUE;
 | 
				
			||||||
 | 
							sr_session_send_meta(sdi, SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE,
 | 
				
			||||||
 | 
								g_variant_new_boolean(TRUE));
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (g_str_has_prefix((const char *)devc->buf, "undervolt")) {
 | 
						if (g_str_has_prefix((const char *)devc->buf, "undervolt")) {
 | 
				
			||||||
		sr_warn("Undervoltage condition!");
 | 
							sr_warn("Undervoltage condition!");
 | 
				
			||||||
		devc->uvc_active = TRUE;
 | 
							devc->uvc_active = TRUE;
 | 
				
			||||||
 | 
							sr_session_send_meta(sdi, SR_CONF_UNDER_VOLTAGE_CONDITION_ACTIVE,
 | 
				
			||||||
 | 
								g_variant_new_boolean(TRUE));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (g_str_has_prefix((const char *)devc->buf, "err ")) {
 | 
				
			||||||
 | 
							sr_err("Device replied with an error: '%s'.", devc->buf);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (g_str_has_prefix((const char *)devc->buf, "set ")) {
 | 
				
			||||||
 | 
							tokens = g_strsplit((const char *)devc->buf, " ", 2);
 | 
				
			||||||
 | 
							devc->current_limit = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
				
			||||||
 | 
							g_strfreev(tokens);
 | 
				
			||||||
 | 
							g_cond_signal(&devc->current_limit_cond);
 | 
				
			||||||
 | 
							sr_session_send_meta(sdi, SR_CONF_CURRENT_LIMIT,
 | 
				
			||||||
 | 
								g_variant_new_double(devc->current_limit));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (g_str_has_prefix((const char *)devc->buf, "uvlo ")) {
 | 
				
			||||||
 | 
							tokens = g_strsplit((const char *)devc->buf, " ", 2);
 | 
				
			||||||
 | 
							devc->uvc_threshold = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
				
			||||||
 | 
							g_strfreev(tokens);
 | 
				
			||||||
 | 
							g_cond_signal(&devc->uvc_threshold_cond);
 | 
				
			||||||
 | 
							if (devc->uvc_threshold == .0) {
 | 
				
			||||||
 | 
								sr_session_send_meta(sdi, SR_CONF_UNDER_VOLTAGE_CONDITION,
 | 
				
			||||||
 | 
									g_variant_new_boolean(FALSE));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sr_session_send_meta(sdi, SR_CONF_UNDER_VOLTAGE_CONDITION,
 | 
				
			||||||
 | 
									g_variant_new_boolean(TRUE));
 | 
				
			||||||
 | 
								sr_session_send_meta(sdi,
 | 
				
			||||||
 | 
									SR_CONF_UNDER_VOLTAGE_CONDITION_THRESHOLD,
 | 
				
			||||||
 | 
									g_variant_new_double(devc->uvc_threshold));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,14 +333,13 @@ static void handle_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tokens = g_strsplit((const char *)devc->buf, " ", 3);
 | 
						tokens = g_strsplit((const char *)devc->buf, " ", 3);
 | 
				
			||||||
	voltage = g_ascii_strtod(tokens[2], NULL) / 1000;
 | 
						devc->voltage = g_ascii_strtod(tokens[2], NULL) / 1000;
 | 
				
			||||||
	current = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
						devc->current = g_ascii_strtod(tokens[1], NULL) / 1000;
 | 
				
			||||||
	g_strfreev(tokens);
 | 
						g_strfreev(tokens);
 | 
				
			||||||
 | 
						g_cond_signal(&devc->voltage_cond);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Begin frame. */
 | 
						/* Begin frame. */
 | 
				
			||||||
	packet.type = SR_DF_FRAME_BEGIN;
 | 
						std_session_send_df_frame_begin(sdi);
 | 
				
			||||||
	packet.payload = NULL;
 | 
					 | 
				
			||||||
	sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_analog_init(&analog, &encoding, &meaning, &spec, 4);
 | 
						sr_analog_init(&analog, &encoding, &meaning, &spec, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -197,7 +354,8 @@ static void handle_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	meaning.mq = SR_MQ_VOLTAGE;
 | 
						meaning.mq = SR_MQ_VOLTAGE;
 | 
				
			||||||
	meaning.mqflags = SR_MQFLAG_DC;
 | 
						meaning.mqflags = SR_MQFLAG_DC;
 | 
				
			||||||
	meaning.unit = SR_UNIT_VOLT;
 | 
						meaning.unit = SR_UNIT_VOLT;
 | 
				
			||||||
	analog.data = &voltage;
 | 
						encoding.digits = 3;
 | 
				
			||||||
 | 
						analog.data = &devc->voltage;
 | 
				
			||||||
	sr_session_send(sdi, &packet);
 | 
						sr_session_send(sdi, &packet);
 | 
				
			||||||
	g_slist_free(l);
 | 
						g_slist_free(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -208,14 +366,13 @@ static void handle_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	meaning.mq = SR_MQ_CURRENT;
 | 
						meaning.mq = SR_MQ_CURRENT;
 | 
				
			||||||
	meaning.mqflags = SR_MQFLAG_DC;
 | 
						meaning.mqflags = SR_MQFLAG_DC;
 | 
				
			||||||
	meaning.unit = SR_UNIT_AMPERE;
 | 
						meaning.unit = SR_UNIT_AMPERE;
 | 
				
			||||||
	analog.data = ¤t;
 | 
						encoding.digits = 3;
 | 
				
			||||||
 | 
						analog.data = &devc->current;
 | 
				
			||||||
	sr_session_send(sdi, &packet);
 | 
						sr_session_send(sdi, &packet);
 | 
				
			||||||
	g_slist_free(l);
 | 
						g_slist_free(l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* End frame. */
 | 
						/* End frame. */
 | 
				
			||||||
	packet.type = SR_DF_FRAME_END;
 | 
						std_session_send_df_frame_end(sdi);
 | 
				
			||||||
	packet.payload = NULL;
 | 
					 | 
				
			||||||
	sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
						sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -225,27 +382,35 @@ static void handle_new_data(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Try to get as much data as the buffer can hold. */
 | 
					 | 
				
			||||||
	len = RELOADPRO_BUFSIZE - devc->buflen;
 | 
						len = RELOADPRO_BUFSIZE - devc->buflen;
 | 
				
			||||||
	len = serial_read_nonblocking(serial, devc->buf + devc->buflen, len);
 | 
						buf = devc->buf;
 | 
				
			||||||
	if (len == 0)
 | 
						g_mutex_lock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
						if (serial_readline(serial, &buf, &len, 250) != SR_OK) {
 | 
				
			||||||
 | 
							g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len == 0) {
 | 
				
			||||||
 | 
							g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
		return; /* No new bytes, nothing to do. */
 | 
							return; /* No new bytes, nothing to do. */
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (len < 0) {
 | 
						if (len < 0) {
 | 
				
			||||||
		sr_err("Serial port read error: %d.", len);
 | 
							sr_err("Serial port read error: %d.", len);
 | 
				
			||||||
 | 
							g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	devc->buflen += len;
 | 
						devc->buflen += len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (g_str_has_suffix((const char *)devc->buf, "\n")) {
 | 
					 | 
				
			||||||
	handle_packet(sdi);
 | 
						handle_packet(sdi);
 | 
				
			||||||
 | 
						g_mutex_unlock(&devc->acquisition_mutex);
 | 
				
			||||||
	memset(devc->buf, 0, RELOADPRO_BUFSIZE);
 | 
						memset(devc->buf, 0, RELOADPRO_BUFSIZE);
 | 
				
			||||||
	devc->buflen = 0;
 | 
						devc->buflen = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int reloadpro_receive_data(int fd, int revents, void *cb_data)
 | 
					SR_PRIV int reloadpro_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -263,7 +428,7 @@ SR_PRIV int reloadpro_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	handle_new_data(sdi);
 | 
						handle_new_data(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->limits))
 | 
						if (sr_sw_limits_check(&devc->limits))
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,24 +25,40 @@
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOG_PREFIX "re-load-pro"
 | 
					#define LOG_PREFIX "arachnid-labs-re-load-pro"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RELOADPRO_BUFSIZE 100
 | 
					#define RELOADPRO_BUFSIZE 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
						struct sr_sw_limits limits;
 | 
				
			||||||
	uint8_t buf[RELOADPRO_BUFSIZE];
 | 
					
 | 
				
			||||||
 | 
						char buf[RELOADPRO_BUFSIZE];
 | 
				
			||||||
	int buflen;
 | 
						int buflen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						float current_limit;
 | 
				
			||||||
 | 
						float voltage;
 | 
				
			||||||
 | 
						float current;
 | 
				
			||||||
	gboolean otp_active;
 | 
						gboolean otp_active;
 | 
				
			||||||
	gboolean uvc_active;
 | 
						gboolean uvc_active;
 | 
				
			||||||
 | 
						float uvc_threshold;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gboolean acquisition_running;
 | 
				
			||||||
 | 
						GMutex acquisition_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GCond current_limit_cond;
 | 
				
			||||||
 | 
						GCond voltage_cond;
 | 
				
			||||||
 | 
						GCond uvc_threshold_cond;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int reloadpro_set_current_limit(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_set_current_limit(const struct sr_dev_inst *sdi,
 | 
				
			||||||
		float current);
 | 
							float current);
 | 
				
			||||||
SR_PRIV int reloadpro_set_on_off(const struct sr_dev_inst *sdi, gboolean on);
 | 
					SR_PRIV int reloadpro_set_on_off(const struct sr_dev_inst *sdi, gboolean on);
 | 
				
			||||||
 | 
					SR_PRIV int reloadpro_set_under_voltage_threshold(const struct sr_dev_inst *sdi,
 | 
				
			||||||
 | 
							float uvc_threshold);
 | 
				
			||||||
SR_PRIV int reloadpro_get_current_limit(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_get_current_limit(const struct sr_dev_inst *sdi,
 | 
				
			||||||
		float *current);
 | 
							float *current_limit);
 | 
				
			||||||
 | 
					SR_PRIV int reloadpro_get_under_voltage_threshold(const struct sr_dev_inst *sdi,
 | 
				
			||||||
 | 
							float *uvc_threshold);
 | 
				
			||||||
SR_PRIV int reloadpro_get_voltage_current(const struct sr_dev_inst *sdi,
 | 
					SR_PRIV int reloadpro_get_voltage_current(const struct sr_dev_inst *sdi,
 | 
				
			||||||
		float *voltage, float *current);
 | 
							float *voltage, float *current);
 | 
				
			||||||
SR_PRIV int reloadpro_receive_data(int fd, int revents, void *cb_data);
 | 
					SR_PRIV int reloadpro_receive_data(int fd, int revents, void *cb_data);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
 * Copyright (C) 2010-2012 Håvard Espeland <gus@ping.uio.no>,
 | 
					 * Copyright (C) 2010-2012 Håvard Espeland <gus@ping.uio.no>,
 | 
				
			||||||
 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
 | 
					 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
 | 
				
			||||||
 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
 | 
					 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Gerhard Sittig <gerhard.sittig@gmx.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -19,23 +20,23 @@
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * ASIX SIGMA/SIGMA2 logic analyzer driver
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Channel numbers seem to go from 1-16, according to this image:
 | 
					 * Channels are labelled 1-16, see this vendor's image of the cable:
 | 
				
			||||||
 * http://tools.asix.net/img/sigma_sigmacab_pins_720.jpg
 | 
					 * http://tools.asix.net/img/sigma_sigmacab_pins_720.jpg (TI/TO are
 | 
				
			||||||
 * (the cable has two additional GND pins, and a TI and TO pin)
 | 
					 * additional trigger in/out signals).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const char *channel_names[] = {
 | 
					static const char *channel_names[] = {
 | 
				
			||||||
	"1", "2", "3", "4", "5", "6", "7", "8",
 | 
						"1", "2", "3", "4", "5", "6", "7", "8",
 | 
				
			||||||
	"9", "10", "11", "12", "13", "14", "15", "16",
 | 
						"9", "10", "11", "12", "13", "14", "15", "16",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t scanopts[] = {
 | 
				
			||||||
 | 
						SR_CONF_CONN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t drvopts[] = {
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
	SR_CONF_LOGIC_ANALYZER,
 | 
						SR_CONF_LOGIC_ANALYZER,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -43,116 +44,232 @@ static const uint32_t drvopts[] = {
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
	SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
 | 
						SR_CONF_CONN | SR_CONF_GET,
 | 
				
			||||||
	SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
						SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
						SR_CONF_EXTERNAL_CLOCK | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
 | 
						SR_CONF_EXTERNAL_CLOCK_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
 | 
						SR_CONF_CLOCK_EDGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
 | 
						SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
#endif
 | 
						/* Consider SR_CONF_TRIGGER_PATTERN (SR_T_STRING, GET/SET) support. */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *ext_clock_edges[] = {
 | 
				
			||||||
 | 
						[SIGMA_CLOCK_EDGE_RISING] = "rising",
 | 
				
			||||||
 | 
						[SIGMA_CLOCK_EDGE_FALLING] = "falling",
 | 
				
			||||||
 | 
						[SIGMA_CLOCK_EDGE_EITHER] = "either",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
					 | 
				
			||||||
static const int32_t trigger_matches[] = {
 | 
					static const int32_t trigger_matches[] = {
 | 
				
			||||||
	SR_TRIGGER_ZERO,
 | 
						SR_TRIGGER_ZERO,
 | 
				
			||||||
	SR_TRIGGER_ONE,
 | 
						SR_TRIGGER_ONE,
 | 
				
			||||||
	SR_TRIGGER_RISING,
 | 
						SR_TRIGGER_RISING,
 | 
				
			||||||
	SR_TRIGGER_FALLING,
 | 
						SR_TRIGGER_FALLING,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					
 | 
				
			||||||
 | 
					static void clear_helper(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						(void)sigma_force_close(devc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_clear(const struct sr_dev_driver *di)
 | 
					static int dev_clear(const struct sr_dev_driver *di)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return std_dev_clear(di, sigma_clear_helper);
 | 
						return std_dev_clear_with_callback(di,
 | 
				
			||||||
 | 
							(std_dev_clear_callback)clear_helper);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean bus_addr_in_devices(int bus, int addr, GSList *devs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sr_usb_dev_inst *usb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (/* EMPTY */; devs; devs = devs->next) {
 | 
				
			||||||
 | 
							usb = devs->data;
 | 
				
			||||||
 | 
							if (usb->bus == bus && usb->address == addr)
 | 
				
			||||||
 | 
								return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static gboolean known_vid_pid(const struct libusb_device_descriptor *des)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						gboolean is_sigma, is_omega;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (des->idVendor != USB_VENDOR_ASIX)
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						is_sigma = des->idProduct == USB_PRODUCT_SIGMA;
 | 
				
			||||||
 | 
						is_omega = des->idProduct == USB_PRODUCT_OMEGA;
 | 
				
			||||||
 | 
						if (!is_sigma && !is_omega)
 | 
				
			||||||
 | 
							return FALSE;
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct drv_context *drvc;
 | 
				
			||||||
 | 
						libusb_context *usbctx;
 | 
				
			||||||
 | 
						const char *conn;
 | 
				
			||||||
 | 
						GSList *l, *conn_devices;
 | 
				
			||||||
 | 
						struct sr_config *src;
 | 
				
			||||||
 | 
						GSList *devices;
 | 
				
			||||||
 | 
						libusb_device **devlist, *devitem;
 | 
				
			||||||
 | 
						int bus, addr;
 | 
				
			||||||
 | 
						struct libusb_device_descriptor des;
 | 
				
			||||||
 | 
						struct libusb_device_handle *hdl;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char conn_id[20];
 | 
				
			||||||
 | 
						char serno_txt[16];
 | 
				
			||||||
 | 
						char *end;
 | 
				
			||||||
 | 
						unsigned long serno_num, serno_pre;
 | 
				
			||||||
 | 
						enum asix_device_type dev_type;
 | 
				
			||||||
 | 
						const char *dev_text;
 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
						struct sr_dev_inst *sdi;
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct ftdi_device_list *devlist;
 | 
						size_t devidx, chidx;
 | 
				
			||||||
	char serial_txt[10];
 | 
					 | 
				
			||||||
	uint32_t serial;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)options;
 | 
						drvc = di->context;
 | 
				
			||||||
 | 
						usbctx = drvc->sr_ctx->libusb_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = g_malloc0(sizeof(struct dev_context));
 | 
						/* Find all devices which match an (optional) conn= spec. */
 | 
				
			||||||
 | 
						conn = NULL;
 | 
				
			||||||
	ftdi_init(&devc->ftdic);
 | 
						for (l = options; l; l = l->next) {
 | 
				
			||||||
 | 
							src = l->data;
 | 
				
			||||||
	/* Look for SIGMAs. */
 | 
							switch (src->key) {
 | 
				
			||||||
 | 
							case SR_CONF_CONN:
 | 
				
			||||||
	if ((ret = ftdi_usb_find_all(&devc->ftdic, &devlist,
 | 
								conn = g_variant_get_string(src->data, NULL);
 | 
				
			||||||
	    USB_VENDOR, USB_PRODUCT)) <= 0) {
 | 
								break;
 | 
				
			||||||
		if (ret < 0)
 | 
					 | 
				
			||||||
			sr_err("ftdi_usb_find_all(): %d", ret);
 | 
					 | 
				
			||||||
		goto free;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Make sure it's a version 1 or 2 SIGMA. */
 | 
					 | 
				
			||||||
	ftdi_usb_get_strings(&devc->ftdic, devlist->dev, NULL, 0, NULL, 0,
 | 
					 | 
				
			||||||
			     serial_txt, sizeof(serial_txt));
 | 
					 | 
				
			||||||
	sscanf(serial_txt, "%x", &serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (serial < 0xa6010000 || serial > 0xa602ffff) {
 | 
					 | 
				
			||||||
		sr_err("Only SIGMA and SIGMA2 are supported "
 | 
					 | 
				
			||||||
		       "in this version of libsigrok.");
 | 
					 | 
				
			||||||
		goto free;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						conn_devices = NULL;
 | 
				
			||||||
	sr_info("Found ASIX SIGMA - Serial: %s", serial_txt);
 | 
						if (conn)
 | 
				
			||||||
 | 
							conn_devices = sr_usb_find(usbctx, conn);
 | 
				
			||||||
	devc->cur_samplerate = samplerates[0];
 | 
						if (conn && !conn_devices)
 | 
				
			||||||
	devc->limit_msec = 0;
 | 
					 | 
				
			||||||
	devc->limit_samples = 0;
 | 
					 | 
				
			||||||
	devc->cur_firmware = -1;
 | 
					 | 
				
			||||||
	devc->num_channels = 0;
 | 
					 | 
				
			||||||
	devc->samples_per_event = 0;
 | 
					 | 
				
			||||||
	devc->capture_ratio = 50;
 | 
					 | 
				
			||||||
	devc->use_triggers = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Register SIGMA device. */
 | 
					 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INITIALIZING;
 | 
					 | 
				
			||||||
	sdi->vendor = g_strdup(USB_VENDOR_NAME);
 | 
					 | 
				
			||||||
	sdi->model = g_strdup(USB_MODEL_NAME);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(channel_names); i++)
 | 
					 | 
				
			||||||
		sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_names[i]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi->priv = devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* We will open the device again when we need it. */
 | 
					 | 
				
			||||||
	ftdi_list_free(&devlist);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
free:
 | 
					 | 
				
			||||||
	ftdi_deinit(&devc->ftdic);
 | 
					 | 
				
			||||||
	g_free(devc);
 | 
					 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find all ASIX logic analyzers (which match the connection spec). */
 | 
				
			||||||
 | 
						devices = NULL;
 | 
				
			||||||
 | 
						libusb_get_device_list(usbctx, &devlist);
 | 
				
			||||||
 | 
						for (devidx = 0; devlist[devidx]; devidx++) {
 | 
				
			||||||
 | 
							devitem = devlist[devidx];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Check for connection match if a user spec was given. */
 | 
				
			||||||
 | 
							bus = libusb_get_bus_number(devitem);
 | 
				
			||||||
 | 
							addr = libusb_get_device_address(devitem);
 | 
				
			||||||
 | 
							if (conn && !bus_addr_in_devices(bus, addr, conn_devices))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							snprintf(conn_id, sizeof(conn_id), "%d.%d", bus, addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Check for known VID:PID pairs. Get the serial number,
 | 
				
			||||||
 | 
							 * to then derive the device type from it.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							libusb_get_device_descriptor(devitem, &des);
 | 
				
			||||||
 | 
							if (!known_vid_pid(&des))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (!des.iSerialNumber) {
 | 
				
			||||||
 | 
								sr_warn("Cannot get serial number (index 0).");
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ret = libusb_open(devitem, &hdl);
 | 
				
			||||||
 | 
							if (ret < 0) {
 | 
				
			||||||
 | 
								sr_warn("Cannot open USB device %04x.%04x: %s.",
 | 
				
			||||||
 | 
									des.idVendor, des.idProduct,
 | 
				
			||||||
 | 
									libusb_error_name(ret));
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ret = libusb_get_string_descriptor_ascii(hdl,
 | 
				
			||||||
 | 
								des.iSerialNumber,
 | 
				
			||||||
 | 
								(unsigned char *)serno_txt, sizeof(serno_txt));
 | 
				
			||||||
 | 
							if (ret < 0) {
 | 
				
			||||||
 | 
								sr_warn("Cannot get serial number (%s).",
 | 
				
			||||||
 | 
									libusb_error_name(ret));
 | 
				
			||||||
 | 
								libusb_close(hdl);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							libusb_close(hdl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * All ASIX logic analyzers have a serial number, which
 | 
				
			||||||
 | 
							 * reads as a hex number, and tells the device type.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ret = sr_atoul_base(serno_txt, &serno_num, &end, 16);
 | 
				
			||||||
 | 
							if (ret != SR_OK || !end || *end) {
 | 
				
			||||||
 | 
								sr_warn("Cannot interpret serial number %s.", serno_txt);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							dev_type = ASIX_TYPE_NONE;
 | 
				
			||||||
 | 
							dev_text = NULL;
 | 
				
			||||||
 | 
							serno_pre = serno_num >> 16;
 | 
				
			||||||
 | 
							switch (serno_pre) {
 | 
				
			||||||
 | 
							case 0xa601:
 | 
				
			||||||
 | 
								dev_type = ASIX_TYPE_SIGMA;
 | 
				
			||||||
 | 
								dev_text = "SIGMA";
 | 
				
			||||||
 | 
								sr_info("Found SIGMA, serno %s.", serno_txt);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 0xa602:
 | 
				
			||||||
 | 
								dev_type = ASIX_TYPE_SIGMA;
 | 
				
			||||||
 | 
								dev_text = "SIGMA2";
 | 
				
			||||||
 | 
								sr_info("Found SIGMA2, serno %s.", serno_txt);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case 0xa603:
 | 
				
			||||||
 | 
								dev_type = ASIX_TYPE_OMEGA;
 | 
				
			||||||
 | 
								dev_text = "OMEGA";
 | 
				
			||||||
 | 
								sr_info("Found OMEGA, serno %s.", serno_txt);
 | 
				
			||||||
 | 
								if (!ASIX_WITH_OMEGA) {
 | 
				
			||||||
 | 
									sr_warn("OMEGA support is not implemented yet.");
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								sr_warn("Unknown serno %s, skipping.", serno_txt);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Create a device instance, add it to the result set. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sdi = g_malloc0(sizeof(*sdi));
 | 
				
			||||||
 | 
							devices = g_slist_append(devices, sdi);
 | 
				
			||||||
 | 
							sdi->status = SR_ST_INITIALIZING;
 | 
				
			||||||
 | 
							sdi->vendor = g_strdup("ASIX");
 | 
				
			||||||
 | 
							sdi->model = g_strdup(dev_text);
 | 
				
			||||||
 | 
							sdi->serial_num = g_strdup(serno_txt);
 | 
				
			||||||
 | 
							sdi->connection_id = g_strdup(conn_id);
 | 
				
			||||||
 | 
							for (chidx = 0; chidx < ARRAY_SIZE(channel_names); chidx++)
 | 
				
			||||||
 | 
								sr_channel_new(sdi, chidx, SR_CHANNEL_LOGIC,
 | 
				
			||||||
 | 
									TRUE, channel_names[chidx]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							devc = g_malloc0(sizeof(*devc));
 | 
				
			||||||
 | 
							sdi->priv = devc;
 | 
				
			||||||
 | 
							devc->id.vid = des.idVendor;
 | 
				
			||||||
 | 
							devc->id.pid = des.idProduct;
 | 
				
			||||||
 | 
							devc->id.serno = serno_num;
 | 
				
			||||||
 | 
							devc->id.prefix = serno_pre;
 | 
				
			||||||
 | 
							devc->id.type = dev_type;
 | 
				
			||||||
 | 
							sr_sw_limits_init(&devc->limit.config);
 | 
				
			||||||
 | 
							devc->capture_ratio = 50;
 | 
				
			||||||
 | 
							devc->use_triggers = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Get current hardware configuration (or use defaults). */
 | 
				
			||||||
 | 
							(void)sigma_fetch_hw_config(sdi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						libusb_free_device_list(devlist, 1);
 | 
				
			||||||
 | 
						g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return std_scan_complete(di, devices);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_open(struct sr_dev_inst *sdi)
 | 
					static int dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Make sure it's an ASIX SIGMA. */
 | 
						if (devc->id.type == ASIX_TYPE_OMEGA && !ASIX_WITH_OMEGA) {
 | 
				
			||||||
	if ((ret = ftdi_usb_open_desc(&devc->ftdic,
 | 
							sr_err("OMEGA support is not implemented yet.");
 | 
				
			||||||
		USB_VENDOR, USB_PRODUCT, USB_DESCRIPTION, NULL)) < 0) {
 | 
							return SR_ERR_NA;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		sr_err("ftdi_usb_open failed: %s",
 | 
					 | 
				
			||||||
		       ftdi_get_error_string(&devc->ftdic));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi->status = SR_ST_ACTIVE;
 | 
						return sigma_force_open(sdi);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_close(struct sr_dev_inst *sdi)
 | 
					static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -161,19 +278,14 @@ static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* TODO */
 | 
						return sigma_force_close(devc);
 | 
				
			||||||
	if (sdi->status == SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		ftdi_usb_close(&devc->ftdic);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						const char *clock_text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -182,20 +294,29 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
 | 
						case SR_CONF_CONN:
 | 
				
			||||||
 | 
							*data = g_variant_new_string(sdi->connection_id);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->cur_samplerate);
 | 
							*data = g_variant_new_uint64(devc->clock.samplerate);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_EXTERNAL_CLOCK:
 | 
				
			||||||
 | 
							*data = g_variant_new_boolean(devc->clock.use_ext_clock);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_EXTERNAL_CLOCK_SOURCE:
 | 
				
			||||||
 | 
							clock_text = channel_names[devc->clock.clock_pin];
 | 
				
			||||||
 | 
							*data = g_variant_new_string(clock_text);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_CLOCK_EDGE:
 | 
				
			||||||
 | 
							clock_text = ext_clock_edges[devc->clock.clock_edge];
 | 
				
			||||||
 | 
							*data = g_variant_new_string(clock_text);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->limit_msec);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->limit_samples);
 | 
							return sr_sw_limits_config_get(&devc->limit.config, key, data);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
					 | 
				
			||||||
	case SR_CONF_CAPTURE_RATIO:
 | 
						case SR_CONF_CAPTURE_RATIO:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->capture_ratio);
 | 
							*data = g_variant_new_uint64(devc->capture_ratio);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -203,83 +324,85 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	uint64_t tmp;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
						uint64_t want_rate, have_rate;
 | 
				
			||||||
 | 
						int idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		ret = sigma_set_samplerate(sdi, g_variant_get_uint64(data));
 | 
							want_rate = g_variant_get_uint64(data);
 | 
				
			||||||
 | 
							ret = sigma_normalize_samplerate(want_rate, &have_rate);
 | 
				
			||||||
 | 
							if (ret != SR_OK)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							if (have_rate != want_rate) {
 | 
				
			||||||
 | 
								char *text_want, *text_have;
 | 
				
			||||||
 | 
								text_want = sr_samplerate_string(want_rate);
 | 
				
			||||||
 | 
								text_have = sr_samplerate_string(have_rate);
 | 
				
			||||||
 | 
								sr_info("Adjusted samplerate %s to %s.",
 | 
				
			||||||
 | 
									text_want, text_have);
 | 
				
			||||||
 | 
								g_free(text_want);
 | 
				
			||||||
 | 
								g_free(text_have);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							devc->clock.samplerate = have_rate;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_EXTERNAL_CLOCK:
 | 
				
			||||||
 | 
							devc->clock.use_ext_clock = g_variant_get_boolean(data);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_EXTERNAL_CLOCK_SOURCE:
 | 
				
			||||||
 | 
							idx = std_str_idx(data, ARRAY_AND_SIZE(channel_names));
 | 
				
			||||||
 | 
							if (idx < 0)
 | 
				
			||||||
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
 | 
							devc->clock.clock_pin = idx;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_CLOCK_EDGE:
 | 
				
			||||||
 | 
							idx = std_str_idx(data, ARRAY_AND_SIZE(ext_clock_edges));
 | 
				
			||||||
 | 
							if (idx < 0)
 | 
				
			||||||
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
 | 
							devc->clock.clock_edge = idx;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		tmp = g_variant_get_uint64(data);
 | 
					 | 
				
			||||||
		if (tmp > 0)
 | 
					 | 
				
			||||||
			devc->limit_msec = g_variant_get_uint64(data);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			ret = SR_ERR;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		tmp = g_variant_get_uint64(data);
 | 
							return sr_sw_limits_config_set(&devc->limit.config, key, data);
 | 
				
			||||||
		devc->limit_samples = tmp;
 | 
					 | 
				
			||||||
		devc->limit_msec = sigma_limit_samples_to_msec(devc, tmp);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
					 | 
				
			||||||
	case SR_CONF_CAPTURE_RATIO:
 | 
						case SR_CONF_CAPTURE_RATIO:
 | 
				
			||||||
		tmp = g_variant_get_uint64(data);
 | 
							devc->capture_ratio = g_variant_get_uint64(data);
 | 
				
			||||||
		if (tmp > 100)
 | 
					 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		devc->capture_ratio = tmp;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GVariant *gvar;
 | 
					 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
		if (!sdi)
 | 
							if (cg)
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								return SR_ERR_NA;
 | 
				
			||||||
					drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg,
 | 
				
			||||||
		else
 | 
								scanopts, drvopts, devopts);
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
 | 
							*data = sigma_get_samplerates_list();
 | 
				
			||||||
		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
 | 
							break;
 | 
				
			||||||
				samplerates_count, sizeof(samplerates[0]));
 | 
						case SR_CONF_EXTERNAL_CLOCK_SOURCE:
 | 
				
			||||||
		g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(channel_names));
 | 
				
			||||||
		*data = g_variant_builder_end(&gvb);
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_CLOCK_EDGE:
 | 
				
			||||||
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(ext_clock_edges));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
					 | 
				
			||||||
	case SR_CONF_TRIGGER_MATCH:
 | 
						case SR_CONF_TRIGGER_MATCH:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
 | 
							*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
 | 
				
			||||||
				trigger_matches, ARRAY_SIZE(trigger_matches),
 | 
					 | 
				
			||||||
				sizeof(int32_t));
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -290,118 +413,194 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct clockselect_50 clockselect;
 | 
						uint16_t pindis_mask;
 | 
				
			||||||
	int triggerpin, ret;
 | 
						uint8_t async, div;
 | 
				
			||||||
	uint8_t triggerselect;
 | 
						int ret;
 | 
				
			||||||
 | 
						size_t triggerpin;
 | 
				
			||||||
 | 
						uint8_t trigsel2;
 | 
				
			||||||
	struct triggerinout triggerinout_conf;
 | 
						struct triggerinout triggerinout_conf;
 | 
				
			||||||
	struct triggerlut lut;
 | 
						struct triggerlut lut;
 | 
				
			||||||
	uint8_t regval;
 | 
						uint8_t regval, cmd_bytes[4], *wrptr;
 | 
				
			||||||
	uint8_t clock_bytes[sizeof(clockselect)];
 | 
					 | 
				
			||||||
	size_t clock_idx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sigma_convert_trigger(sdi) != SR_OK) {
 | 
						/* Convert caller's trigger spec to driver's internal format. */
 | 
				
			||||||
		sr_err("Failed to configure triggers.");
 | 
						ret = sigma_convert_trigger(sdi);
 | 
				
			||||||
		return SR_ERR;
 | 
						if (ret != SR_OK) {
 | 
				
			||||||
	}
 | 
							sr_err("Could not configure triggers.");
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If the samplerate has not been set, default to 200 kHz. */
 | 
					 | 
				
			||||||
	if (devc->cur_firmware == -1) {
 | 
					 | 
				
			||||||
		if ((ret = sigma_set_samplerate(sdi, SR_KHZ(200))) != SR_OK)
 | 
					 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enter trigger programming mode. */
 | 
						/*
 | 
				
			||||||
	sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20, devc);
 | 
						 * Setup the device's samplerate from the value which up to now
 | 
				
			||||||
 | 
						 * just got checked and stored. As a byproduct this can pick and
 | 
				
			||||||
 | 
						 * send firmware to the device, reduce the number of available
 | 
				
			||||||
 | 
						 * logic channels, etc.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Determine an acquisition timeout from optionally configured
 | 
				
			||||||
 | 
						 * sample count or time limits. Which depends on the samplerate.
 | 
				
			||||||
 | 
						 * Force 50MHz samplerate when external clock is in use.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (devc->clock.use_ext_clock) {
 | 
				
			||||||
 | 
							if (devc->clock.samplerate != SR_MHZ(50))
 | 
				
			||||||
 | 
								sr_info("External clock, forcing 50MHz samplerate.");
 | 
				
			||||||
 | 
							devc->clock.samplerate = SR_MHZ(50);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ret = sigma_set_samplerate(sdi);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
						ret = sigma_set_acquire_timeout(devc);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	triggerselect = 0;
 | 
						/* Enter trigger programming mode. */
 | 
				
			||||||
	if (devc->cur_samplerate >= SR_MHZ(100)) {
 | 
						trigsel2 = TRGSEL2_RESET;
 | 
				
			||||||
 | 
						ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, trigsel2);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trigsel2 = 0;
 | 
				
			||||||
 | 
						if (devc->clock.samplerate >= SR_MHZ(100)) {
 | 
				
			||||||
		/* 100 and 200 MHz mode. */
 | 
							/* 100 and 200 MHz mode. */
 | 
				
			||||||
		sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81, devc);
 | 
							/* TODO Decipher the 0x81 magic number's purpose. */
 | 
				
			||||||
 | 
							ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, 0x81);
 | 
				
			||||||
 | 
							if (ret != SR_OK)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Find which pin to trigger on from mask. */
 | 
							/* Find which pin to trigger on from mask. */
 | 
				
			||||||
		for (triggerpin = 0; triggerpin < 8; triggerpin++)
 | 
							for (triggerpin = 0; triggerpin < 8; triggerpin++) {
 | 
				
			||||||
			if ((devc->trigger.risingmask | devc->trigger.fallingmask) &
 | 
								if (devc->trigger.risingmask & BIT(triggerpin))
 | 
				
			||||||
			    (1 << triggerpin))
 | 
					 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								if (devc->trigger.fallingmask & BIT(triggerpin))
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Set trigger pin and light LED on trigger. */
 | 
							/* Set trigger pin and light LED on trigger. */
 | 
				
			||||||
		triggerselect = (1 << LEDSEL1) | (triggerpin & 0x7);
 | 
							trigsel2 = triggerpin & TRGSEL2_PINS_MASK;
 | 
				
			||||||
 | 
							trigsel2 |= TRGSEL2_LEDSEL1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Default rising edge. */
 | 
							/* Default rising edge. */
 | 
				
			||||||
 | 
							/* TODO Documentation disagrees, bit set means _rising_ edge. */
 | 
				
			||||||
		if (devc->trigger.fallingmask)
 | 
							if (devc->trigger.fallingmask)
 | 
				
			||||||
			triggerselect |= 1 << 3;
 | 
								trigsel2 |= TRGSEL2_PINPOL_RISE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if (devc->cur_samplerate <= SR_MHZ(50)) {
 | 
						} else if (devc->clock.samplerate <= SR_MHZ(50)) {
 | 
				
			||||||
		/* All other modes. */
 | 
							/* 50MHz firmware modes. */
 | 
				
			||||||
		sigma_build_basic_trigger(&lut, devc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sigma_write_trigger_lut(&lut, devc);
 | 
							/* Translate application specs to hardware perspective. */
 | 
				
			||||||
 | 
							ret = sigma_build_basic_trigger(devc, &lut);
 | 
				
			||||||
 | 
							if (ret != SR_OK)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0);
 | 
							/* Communicate resulting register values to the device. */
 | 
				
			||||||
 | 
							ret = sigma_write_trigger_lut(devc, &lut);
 | 
				
			||||||
 | 
							if (ret != SR_OK)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							trigsel2 = TRGSEL2_LEDSEL1 | TRGSEL2_LEDSEL0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup trigger in and out pins to default values. */
 | 
						/* Setup trigger in and out pins to default values. */
 | 
				
			||||||
	memset(&triggerinout_conf, 0, sizeof(struct triggerinout));
 | 
						memset(&triggerinout_conf, 0, sizeof(triggerinout_conf));
 | 
				
			||||||
	triggerinout_conf.trgout_bytrigger = 1;
 | 
						triggerinout_conf.trgout_bytrigger = TRUE;
 | 
				
			||||||
	triggerinout_conf.trgout_enable = 1;
 | 
						triggerinout_conf.trgout_enable = TRUE;
 | 
				
			||||||
 | 
						/* TODO
 | 
				
			||||||
	sigma_write_register(WRITE_TRIGGER_OPTION,
 | 
						 * Verify the correctness of this implementation. The previous
 | 
				
			||||||
			     (uint8_t *) &triggerinout_conf,
 | 
						 * version used to assign to a C language struct with bit fields
 | 
				
			||||||
			     sizeof(struct triggerinout), devc);
 | 
						 * which is highly non-portable and hard to guess the resulting
 | 
				
			||||||
 | 
						 * raw memory layout or wire transfer content. The C struct's
 | 
				
			||||||
	/* Go back to normal mode. */
 | 
						 * field names did not match the vendor documentation's names.
 | 
				
			||||||
	sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect, devc);
 | 
						 * Which means that I could not verify "on paper" either. Let's
 | 
				
			||||||
 | 
						 * re-visit this code later during research for trigger support.
 | 
				
			||||||
	/* Set clock select register. */
 | 
					 | 
				
			||||||
	clockselect.async = 0;
 | 
					 | 
				
			||||||
	clockselect.fraction = 1 - 1;		/* Divider 1. */
 | 
					 | 
				
			||||||
	clockselect.disabled_channels = 0x0000;	/* All channels enabled. */
 | 
					 | 
				
			||||||
	if (devc->cur_samplerate == SR_MHZ(200)) {
 | 
					 | 
				
			||||||
		/* Enable 4 channels. */
 | 
					 | 
				
			||||||
		clockselect.disabled_channels = 0xf0ff;
 | 
					 | 
				
			||||||
	} else if (devc->cur_samplerate == SR_MHZ(100)) {
 | 
					 | 
				
			||||||
		/* Enable 8 channels. */
 | 
					 | 
				
			||||||
		clockselect.disabled_channels = 0x00ff;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * 50 MHz mode, or fraction thereof. The 50MHz reference
 | 
					 | 
				
			||||||
		 * can get divided by any integer in the range 1 to 256.
 | 
					 | 
				
			||||||
		 * Divider minus 1 gets written to the hardware.
 | 
					 | 
				
			||||||
		 * (The driver lists a discrete set of sample rates, but
 | 
					 | 
				
			||||||
		 * all of them fit the above description.)
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
		clockselect.fraction = SR_MHZ(50) / devc->cur_samplerate - 1;
 | 
						wrptr = cmd_bytes;
 | 
				
			||||||
 | 
						regval = 0;
 | 
				
			||||||
 | 
						if (triggerinout_conf.trgout_bytrigger)
 | 
				
			||||||
 | 
							regval |= TRGOPT_TRGOOUTEN;
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, regval);
 | 
				
			||||||
 | 
						regval &= ~TRGOPT_CLEAR_MASK;
 | 
				
			||||||
 | 
						if (triggerinout_conf.trgout_enable)
 | 
				
			||||||
 | 
							regval |= TRGOPT_TRGOEN;
 | 
				
			||||||
 | 
						write_u8_inc(&wrptr, regval);
 | 
				
			||||||
 | 
						ret = sigma_write_register(devc, WRITE_TRIGGER_OPTION,
 | 
				
			||||||
 | 
							cmd_bytes, wrptr - cmd_bytes);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Leave trigger programming mode. */
 | 
				
			||||||
 | 
						ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, trigsel2);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Samplerate dependent clock and channels configuration. Some
 | 
				
			||||||
 | 
						 * channels by design are not available at higher clock rates.
 | 
				
			||||||
 | 
						 * Register layout differs between firmware variants (depth 1
 | 
				
			||||||
 | 
						 * with LSB channel mask above 50MHz, depth 4 with more details
 | 
				
			||||||
 | 
						 * up to 50MHz).
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Derive a mask where bits are set for unavailable channels.
 | 
				
			||||||
 | 
						 * Either send the single byte, or the full byte sequence.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						pindis_mask = ~BITS_MASK(devc->interp.num_channels);
 | 
				
			||||||
 | 
						if (devc->clock.samplerate > SR_MHZ(50)) {
 | 
				
			||||||
 | 
							ret = sigma_set_register(devc, WRITE_CLOCK_SELECT,
 | 
				
			||||||
 | 
								pindis_mask & 0xff);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							wrptr = cmd_bytes;
 | 
				
			||||||
 | 
							/* Select 50MHz base clock, and divider. */
 | 
				
			||||||
 | 
							async = 0;
 | 
				
			||||||
 | 
							div = SR_MHZ(50) / devc->clock.samplerate - 1;
 | 
				
			||||||
 | 
							if (devc->clock.use_ext_clock) {
 | 
				
			||||||
 | 
								async = CLKSEL_CLKSEL8;
 | 
				
			||||||
 | 
								div = devc->clock.clock_pin + 1;
 | 
				
			||||||
 | 
								switch (devc->clock.clock_edge) {
 | 
				
			||||||
 | 
								case SIGMA_CLOCK_EDGE_RISING:
 | 
				
			||||||
 | 
									div |= CLKSEL_RISING;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case SIGMA_CLOCK_EDGE_FALLING:
 | 
				
			||||||
 | 
									div |= CLKSEL_FALLING;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case SIGMA_CLOCK_EDGE_EITHER:
 | 
				
			||||||
 | 
									div |= CLKSEL_RISING;
 | 
				
			||||||
 | 
									div |= CLKSEL_FALLING;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
	clock_idx = 0;
 | 
							}
 | 
				
			||||||
	clock_bytes[clock_idx++] = clockselect.async;
 | 
							write_u8_inc(&wrptr, async);
 | 
				
			||||||
	clock_bytes[clock_idx++] = clockselect.fraction;
 | 
							write_u8_inc(&wrptr, div);
 | 
				
			||||||
	clock_bytes[clock_idx++] = clockselect.disabled_channels & 0xff;
 | 
							write_u16be_inc(&wrptr, pindis_mask);
 | 
				
			||||||
	clock_bytes[clock_idx++] = clockselect.disabled_channels >> 8;
 | 
							ret = sigma_write_register(devc, WRITE_CLOCK_SELECT,
 | 
				
			||||||
	sigma_write_register(WRITE_CLOCK_SELECT, clock_bytes, clock_idx, devc);
 | 
								cmd_bytes, wrptr - cmd_bytes);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Setup maximum post trigger time. */
 | 
						/* Setup maximum post trigger time. */
 | 
				
			||||||
	sigma_set_register(WRITE_POST_TRIGGER,
 | 
						ret = sigma_set_register(devc, WRITE_POST_TRIGGER,
 | 
				
			||||||
			   (devc->capture_ratio * 255) / 100, devc);
 | 
							(devc->capture_ratio * 255) / 100);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Start acqusition. */
 | 
						/* Start acqusition. */
 | 
				
			||||||
	devc->start_time = g_get_monotonic_time();
 | 
					 | 
				
			||||||
	regval = WMR_TRGRES | WMR_SDRAMWRITEEN;
 | 
						regval = WMR_TRGRES | WMR_SDRAMWRITEEN;
 | 
				
			||||||
#if ASIX_SIGMA_WITH_TRIGGER
 | 
						if (devc->use_triggers)
 | 
				
			||||||
		regval |= WMR_TRGEN;
 | 
							regval |= WMR_TRGEN;
 | 
				
			||||||
#endif
 | 
						ret = sigma_set_register(devc, WRITE_MODE, regval);
 | 
				
			||||||
	sigma_set_register(WRITE_MODE, regval, devc);
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						ret = std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Add capture source. */
 | 
						/* Add capture source. */
 | 
				
			||||||
	sr_session_source_add(sdi->session, -1, 0, 10, sigma_receive_data, (void *)sdi);
 | 
						ret = sr_session_source_add(sdi->session, -1, 0, 10,
 | 
				
			||||||
 | 
							sigma_receive_data, (void *)sdi);
 | 
				
			||||||
 | 
						if (ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc->state.state = SIGMA_CAPTURE;
 | 
						devc->state = SIGMA_CAPTURE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -411,9 +610,20 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	devc->state.state = SIGMA_IDLE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_session_source_remove(sdi->session, -1);
 | 
						/*
 | 
				
			||||||
 | 
						 * When acquisition is currently running, keep the receive
 | 
				
			||||||
 | 
						 * routine registered and have it stop the acquisition upon the
 | 
				
			||||||
 | 
						 * next invocation. Else unregister the receive routine here
 | 
				
			||||||
 | 
						 * already. The detour is required to have sample data retrieved
 | 
				
			||||||
 | 
						 * for forced acquisition stops.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (devc->state == SIGMA_CAPTURE) {
 | 
				
			||||||
 | 
							devc->state = SIGMA_STOPPING;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							devc->state = SIGMA_IDLE;
 | 
				
			||||||
 | 
							(void)sr_session_source_remove(sdi->session, -1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
 * Copyright (C) 2010-2012 Håvard Espeland <gus@ping.uio.no>,
 | 
					 * Copyright (C) 2010-2012 Håvard Espeland <gus@ping.uio.no>,
 | 
				
			||||||
 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
 | 
					 * Copyright (C) 2010 Martin Stensgård <mastensg@ping.uio.no>
 | 
				
			||||||
 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
 | 
					 * Copyright (C) 2010 Carl Henrik Lunde <chlunde@ping.uio.no>
 | 
				
			||||||
 | 
					 * Copyright (C) 2020 Gerhard Sittig <gerhard.sittig@gmx.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -30,33 +31,86 @@
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Triggers are not working in this implementation. Stop claiming
 | 
					 | 
				
			||||||
 * support for the feature which effectively is not available, until
 | 
					 | 
				
			||||||
 * the implementation got fixed. Yet keep the code in place and allow
 | 
					 | 
				
			||||||
 * developers to turn on this switch during development.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define ASIX_SIGMA_WITH_TRIGGER	0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define LOG_PREFIX "asix-sigma"
 | 
					#define LOG_PREFIX "asix-sigma"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_VENDOR			0xa600
 | 
					/* Experimental support for OMEGA (scan only, operation is ENOIMPL). */
 | 
				
			||||||
#define USB_PRODUCT			0xa000
 | 
					#define ASIX_WITH_OMEGA 0
 | 
				
			||||||
#define USB_DESCRIPTION			"ASIX SIGMA"
 | 
					
 | 
				
			||||||
#define USB_VENDOR_NAME			"ASIX"
 | 
					#define USB_VENDOR_ASIX			0xa600
 | 
				
			||||||
#define USB_MODEL_NAME			"SIGMA"
 | 
					#define USB_PRODUCT_SIGMA		0xa000
 | 
				
			||||||
 | 
					#define USB_PRODUCT_OMEGA		0xa004
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum asix_device_type {
 | 
				
			||||||
 | 
						ASIX_TYPE_NONE,
 | 
				
			||||||
 | 
						ASIX_TYPE_SIGMA,
 | 
				
			||||||
 | 
						ASIX_TYPE_OMEGA,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Mask to isolate one bit, mask to span a number of bits. */
 | 
				
			||||||
 | 
					#define BIT(pos)		(1UL << (pos))
 | 
				
			||||||
 | 
					#define BITS_MASK(count)	((1UL << (count)) - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HI4(b)			(((b) >> 4) & 0x0f)
 | 
				
			||||||
 | 
					#define LO4(b)			(((b) >> 0) & 0x0f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * FPGA commands are 8bits wide. The upper nibble is a command opcode,
 | 
				
			||||||
 | 
					 * the lower nibble can carry operand values. 8bit register addresses
 | 
				
			||||||
 | 
					 * and 8bit data values get communicated in two steps.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Register access. */
 | 
				
			||||||
 | 
					#define REG_ADDR_LOW		(0x0 << 4)
 | 
				
			||||||
 | 
					#define REG_ADDR_HIGH		(0x1 << 4)
 | 
				
			||||||
 | 
					#define REG_DATA_LOW		(0x2 << 4)
 | 
				
			||||||
 | 
					#define REG_DATA_HIGH_WRITE	(0x3 << 4)
 | 
				
			||||||
 | 
					#define REG_READ_ADDR		(0x4 << 4)
 | 
				
			||||||
 | 
					#define REG_ADDR_ADJUST		BIT(0) /* Auto adjust register address. */
 | 
				
			||||||
 | 
					#define REG_ADDR_DOWN		BIT(1) /* 1 decrement, 0 increment. */
 | 
				
			||||||
 | 
					#define REG_ADDR_INC		(REG_ADDR_ADJUST)
 | 
				
			||||||
 | 
					#define REG_ADDR_DEC		(REG_ADDR_ADJUST | REG_ADDR_DOWN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Sample memory access. */
 | 
				
			||||||
 | 
					#define REG_DRAM_WAIT_ACK	(0x5 << 4) /* Wait for completion. */
 | 
				
			||||||
 | 
					#define REG_DRAM_BLOCK		(0x6 << 4) /* DRAM to BRAM, plus bank select. */
 | 
				
			||||||
 | 
					#define REG_DRAM_BLOCK_BEGIN	(0x8 << 4) /* Read first BRAM bytes. */
 | 
				
			||||||
 | 
					#define REG_DRAM_BLOCK_DATA	(0xa << 4) /* Read full BRAM block. */
 | 
				
			||||||
 | 
					#define REG_DRAM_SEL_N		(0x1 << 4) /* Bank select, added to 6/8/a. */
 | 
				
			||||||
 | 
					#define REG_DRAM_SEL_BOOL(b)	((b) ? REG_DRAM_SEL_N : 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Registers at a specific address can have different meanings depending
 | 
				
			||||||
 | 
					 * on whether data is read or written. This is why direction is part of
 | 
				
			||||||
 | 
					 * the programming language identifiers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The vendor documentation suggests that in addition to the first 16
 | 
				
			||||||
 | 
					 * register addresses which implement the logic analyzer's feature set,
 | 
				
			||||||
 | 
					 * there are 240 more registers in the 16 to 255 address range which
 | 
				
			||||||
 | 
					 * are available to applications and plugin features. Can libsigrok's
 | 
				
			||||||
 | 
					 * asix-sigma driver store configuration data there, to avoid expensive
 | 
				
			||||||
 | 
					 * operations (think: firmware re-load).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Update: The documentation may be incorrect, or the FPGA netlist may
 | 
				
			||||||
 | 
					 * be incomplete. Experiments show that registers beyond 0x0f can get
 | 
				
			||||||
 | 
					 * accessed, USB communication passes, but data bytes are always 0xff.
 | 
				
			||||||
 | 
					 * Are several firmware versions around, and the documentation does not
 | 
				
			||||||
 | 
					 * match the one that ships with sigrok?
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum sigma_write_register {
 | 
					enum sigma_write_register {
 | 
				
			||||||
	WRITE_CLOCK_SELECT	= 0,
 | 
						WRITE_CLOCK_SELECT	= 0,
 | 
				
			||||||
	WRITE_TRIGGER_SELECT0	= 1,
 | 
						WRITE_TRIGGER_SELECT	= 1,
 | 
				
			||||||
	WRITE_TRIGGER_SELECT1	= 2,
 | 
						WRITE_TRIGGER_SELECT2	= 2,
 | 
				
			||||||
	WRITE_MODE		= 3,
 | 
						WRITE_MODE		= 3,
 | 
				
			||||||
	WRITE_MEMROW		= 4,
 | 
						WRITE_MEMROW		= 4,
 | 
				
			||||||
	WRITE_POST_TRIGGER	= 5,
 | 
						WRITE_POST_TRIGGER	= 5,
 | 
				
			||||||
	WRITE_TRIGGER_OPTION	= 6,
 | 
						WRITE_TRIGGER_OPTION	= 6,
 | 
				
			||||||
	WRITE_PIN_VIEW		= 7,
 | 
						WRITE_PIN_VIEW		= 7,
 | 
				
			||||||
 | 
						/* Unassigned register locations. */
 | 
				
			||||||
	WRITE_TEST		= 15,
 | 
						WRITE_TEST		= 15,
 | 
				
			||||||
 | 
						/* Reserved for plugin features. */
 | 
				
			||||||
 | 
						REG_PLUGIN_START	= 16,
 | 
				
			||||||
 | 
						REG_PLUGIN_STOP		= 256,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum sigma_read_register {
 | 
					enum sigma_read_register {
 | 
				
			||||||
| 
						 | 
					@ -72,58 +126,97 @@ enum sigma_read_register {
 | 
				
			||||||
	READ_PIN_CHANGE_HIGH	= 9,
 | 
						READ_PIN_CHANGE_HIGH	= 9,
 | 
				
			||||||
	READ_BLOCK_LAST_TS_LOW	= 10,
 | 
						READ_BLOCK_LAST_TS_LOW	= 10,
 | 
				
			||||||
	READ_BLOCK_LAST_TS_HIGH	= 11,
 | 
						READ_BLOCK_LAST_TS_HIGH	= 11,
 | 
				
			||||||
	READ_PIN_VIEW		= 12,
 | 
						READ_BLOCK_TS_OVERRUN	= 12,
 | 
				
			||||||
 | 
						READ_PIN_VIEW		= 13,
 | 
				
			||||||
 | 
						/* Unassigned register location. */
 | 
				
			||||||
	READ_TEST		= 15,
 | 
						READ_TEST		= 15,
 | 
				
			||||||
 | 
						/* Reserved for plugin features. See above. */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REG_ADDR_LOW		(0x0 << 4)
 | 
					#define CLKSEL_CLKSEL8		BIT(0)
 | 
				
			||||||
#define REG_ADDR_HIGH		(0x1 << 4)
 | 
					#define CLKSEL_PINMASK		BITS_MASK(4)
 | 
				
			||||||
#define REG_DATA_LOW		(0x2 << 4)
 | 
					#define CLKSEL_RISING		BIT(4)
 | 
				
			||||||
#define REG_DATA_HIGH_WRITE	(0x3 << 4)
 | 
					#define CLKSEL_FALLING		BIT(5)
 | 
				
			||||||
#define REG_READ_ADDR		(0x4 << 4)
 | 
					 | 
				
			||||||
#define REG_DRAM_WAIT_ACK	(0x5 << 4)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit (1 << 4) can be low or high (double buffer / cache) */
 | 
					#define TRGSEL_SELINC_MASK	BITS_MASK(2)
 | 
				
			||||||
#define REG_DRAM_BLOCK		(0x6 << 4)
 | 
					#define TRGSEL_SELINC_SHIFT	0
 | 
				
			||||||
#define REG_DRAM_BLOCK_BEGIN	(0x8 << 4)
 | 
					#define TRGSEL_SELRES_MASK	BITS_MASK(2)
 | 
				
			||||||
#define REG_DRAM_BLOCK_DATA	(0xa << 4)
 | 
					#define TRGSEL_SELRES_SHIFT	2
 | 
				
			||||||
 | 
					#define TRGSEL_SELA_MASK	BITS_MASK(2)
 | 
				
			||||||
 | 
					#define TRGSEL_SELA_SHIFT	4
 | 
				
			||||||
 | 
					#define TRGSEL_SELB_MASK	BITS_MASK(2)
 | 
				
			||||||
 | 
					#define TRGSEL_SELB_SHIFT	6
 | 
				
			||||||
 | 
					#define TRGSEL_SELC_MASK	BITS_MASK(2)
 | 
				
			||||||
 | 
					#define TRGSEL_SELC_SHIFT	8
 | 
				
			||||||
 | 
					#define TRGSEL_SELPRESC_MASK	BITS_MASK(4)
 | 
				
			||||||
 | 
					#define TRGSEL_SELPRESC_SHIFT	12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LEDSEL0			6
 | 
					enum trgsel_selcode_t {
 | 
				
			||||||
#define LEDSEL1			7
 | 
						TRGSEL_SELCODE_LEVEL = 0,
 | 
				
			||||||
 | 
						TRGSEL_SELCODE_FALL = 1,
 | 
				
			||||||
 | 
						TRGSEL_SELCODE_RISE = 2,
 | 
				
			||||||
 | 
						TRGSEL_SELCODE_EVENT = 3,
 | 
				
			||||||
 | 
						TRGSEL_SELCODE_NEVER = 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NEXT_REG		1
 | 
					#define TRGSEL2_PINS_MASK	BITS_MASK(3)
 | 
				
			||||||
 | 
					#define TRGSEL2_PINPOL_RISE	BIT(3)
 | 
				
			||||||
#define EVENTS_PER_CLUSTER	7
 | 
					#define TRGSEL2_LUT_ADDR_MASK	BITS_MASK(4)
 | 
				
			||||||
 | 
					#define TRGSEL2_LUT_WRITE	BIT(4)
 | 
				
			||||||
#define CHUNK_SIZE		1024
 | 
					#define TRGSEL2_RESET		BIT(5)
 | 
				
			||||||
 | 
					#define TRGSEL2_LEDSEL0		BIT(6)
 | 
				
			||||||
 | 
					#define TRGSEL2_LEDSEL1		BIT(7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* WRITE_MODE register fields. */
 | 
					/* WRITE_MODE register fields. */
 | 
				
			||||||
#define WMR_SDRAMWRITEEN	(1 << 0)
 | 
					#define WMR_SDRAMWRITEEN	BIT(0)
 | 
				
			||||||
#define WMR_SDRAMREADEN		(1 << 1)
 | 
					#define WMR_SDRAMREADEN		BIT(1)
 | 
				
			||||||
#define WMR_TRGRES		(1 << 2)
 | 
					#define WMR_TRGRES		BIT(2)
 | 
				
			||||||
#define WMR_TRGEN		(1 << 3)
 | 
					#define WMR_TRGEN		BIT(3)
 | 
				
			||||||
#define WMR_FORCESTOP		(1 << 4)
 | 
					#define WMR_FORCESTOP		BIT(4)
 | 
				
			||||||
#define WMR_TRGSW		(1 << 5)
 | 
					#define WMR_TRGSW		BIT(5)
 | 
				
			||||||
/* not used: bit position 6 */
 | 
					/* not used: bit position 6 */
 | 
				
			||||||
#define WMR_SDRAMINIT		(1 << 7)
 | 
					#define WMR_SDRAMINIT		BIT(7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* READ_MODE register fields. */
 | 
					/* READ_MODE register fields. */
 | 
				
			||||||
#define RMR_SDRAMWRITEEN	(1 << 0)
 | 
					#define RMR_SDRAMWRITEEN	BIT(0)
 | 
				
			||||||
#define RMR_SDRAMREADEN		(1 << 1)
 | 
					#define RMR_SDRAMREADEN		BIT(1)
 | 
				
			||||||
/* not used: bit position 2 */
 | 
					/* not used: bit position 2 */
 | 
				
			||||||
#define RMR_TRGEN		(1 << 3)
 | 
					#define RMR_TRGEN		BIT(3)
 | 
				
			||||||
#define RMR_ROUND		(1 << 4)
 | 
					#define RMR_ROUND		BIT(4)
 | 
				
			||||||
#define RMR_TRIGGERED		(1 << 5)
 | 
					#define RMR_TRIGGERED		BIT(5)
 | 
				
			||||||
#define RMR_POSTTRIGGERED	(1 << 6)
 | 
					#define RMR_POSTTRIGGERED	BIT(6)
 | 
				
			||||||
/* not used: bit position 7 */
 | 
					/* not used: bit position 7 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Trigger options. First and second write are similar, but _some_
 | 
				
			||||||
 | 
					 * positions change their meaning.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGIEN		BIT(7)
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOEN		BIT(6)
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOINEN		BIT(5) /* 1st write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGINEG		TRGOPT1_TRGOINEN /* 2nd write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOEVNTEN	BIT(4) /* 1st write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOPIN		TRGOPT1_TRGOEVNTEN /* 2nd write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOOUTEN	BIT(3) /* 1st write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOLONG		TRGOPT1_TRGOOUTEN /* 2nd write */
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOUTR_OUT	BIT(1)
 | 
				
			||||||
 | 
					#define TRGOPT_TRGOUTR_EN	BIT(0)
 | 
				
			||||||
 | 
					#define TRGOPT_CLEAR_MASK	(TRGOPT_TRGOINEN | TRGOPT_TRGOEVNTEN | TRGOPT_TRGOOUTEN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Layout of the sample data DRAM, which will be downloaded to the PC:
 | 
					 * Layout of the sample data DRAM, which will be downloaded to the PC:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Sigma memory is organized in 32K rows. Each row contains 64 clusters.
 | 
					 * Sigma memory is organized in 32K rows. Each row contains 64 clusters.
 | 
				
			||||||
 * Each cluster contains a timestamp (16bit) and 7 samples (16bits each).
 | 
					 * Each cluster contains a timestamp (16bit) and 7 events (16bits each).
 | 
				
			||||||
 * Total memory size is 32K x 64 x 8 x 2 bytes == 32 MB (256 Mbit).
 | 
					 * Events contain 16 bits of sample data (potentially taken at multiple
 | 
				
			||||||
 | 
					 * sample points, see below).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Total memory size is 32K x 64 x 8 x 2 bytes == 32 MiB (256 Mbit). The
 | 
				
			||||||
 | 
					 * size of a memory row is 1024 bytes. Assuming x16 organization of the
 | 
				
			||||||
 | 
					 * memory array, address specs (sample count, trigger position) are kept
 | 
				
			||||||
 | 
					 * in 24bit entities. The upper 15 bit address the "row", the lower 9 bit
 | 
				
			||||||
 | 
					 * refer to the "event" within the row. Because there is one timestamp for
 | 
				
			||||||
 | 
					 * seven events each, one memory row can hold up to 64x7 == 448 events.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Sample data is represented in 16bit quantities. The first sample in
 | 
					 * Sample data is represented in 16bit quantities. The first sample in
 | 
				
			||||||
 * the cluster corresponds to the cluster's timestamp. Each next sample
 | 
					 * the cluster corresponds to the cluster's timestamp. Each next sample
 | 
				
			||||||
| 
						 | 
					@ -131,80 +224,50 @@ enum sigma_read_register {
 | 
				
			||||||
 * one sample period, according to the samplerate). In the absence of
 | 
					 * one sample period, according to the samplerate). In the absence of
 | 
				
			||||||
 * pin level changes, no data is provided (RLE compression). A cluster
 | 
					 * pin level changes, no data is provided (RLE compression). A cluster
 | 
				
			||||||
 * is enforced for each 64K ticks of the timestamp, to reliably handle
 | 
					 * is enforced for each 64K ticks of the timestamp, to reliably handle
 | 
				
			||||||
 * rollover and determination of the next timestamp of the next cluster.
 | 
					 * rollover and determine the next timestamp of the next cluster.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * For samplerates up to 50MHz, an event directly translates to one set
 | 
				
			||||||
 | 
					 * of sample data at a single sample point, spanning up to 16 channels.
 | 
				
			||||||
 * For samplerates of 100MHz, there is one 16 bit entity for each 20ns
 | 
					 * For samplerates of 100MHz, there is one 16 bit entity for each 20ns
 | 
				
			||||||
 * period (50MHz rate). The 16 bit memory contains 2 samples of up to
 | 
					 * period (50MHz rate). The 16 bit memory contains 2 samples of up to
 | 
				
			||||||
 * 8 channels. Bits of multiple samples are interleaved. For samplerates
 | 
					 * 8 channels. Bits of multiple samples are interleaved. For samplerates
 | 
				
			||||||
 * of 200MHz one 16bit entity contains 4 samples of up to 4 channels,
 | 
					 * of 200MHz one 16bit entity contains 4 samples of up to 4 channels,
 | 
				
			||||||
 * each 5ns apart.
 | 
					 * each 5ns apart.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Memory addresses (sample count, trigger position) are kept in 24bit
 | 
					 | 
				
			||||||
 * entities. The upper 15 bit refer to the "row", the lower 9 bit refer
 | 
					 | 
				
			||||||
 * to the "event" within the row. Because there is one timestamp for
 | 
					 | 
				
			||||||
 * seven samples each, one memory row can hold up to 64x7 == 448 samples.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* One "DRAM cluster" contains a timestamp and 7 samples, 16b total. */
 | 
					#define ROW_COUNT		32768
 | 
				
			||||||
struct sigma_dram_cluster {
 | 
					#define ROW_LENGTH_BYTES	1024
 | 
				
			||||||
	uint8_t		timestamp_lo;
 | 
					#define ROW_LENGTH_U16		(ROW_LENGTH_BYTES / sizeof(uint16_t))
 | 
				
			||||||
	uint8_t		timestamp_hi;
 | 
					#define ROW_SHIFT		9 /* log2 of u16 count */
 | 
				
			||||||
	struct {
 | 
					#define ROW_MASK		BITS_MASK(ROW_SHIFT)
 | 
				
			||||||
		uint8_t	sample_hi;
 | 
					#define EVENTS_PER_CLUSTER	7
 | 
				
			||||||
		uint8_t	sample_lo;
 | 
					#define CLUSTERS_PER_ROW	(ROW_LENGTH_U16 / (1 + EVENTS_PER_CLUSTER))
 | 
				
			||||||
	}		samples[7];
 | 
					#define EVENTS_PER_ROW		(CLUSTERS_PER_ROW * EVENTS_PER_CLUSTER)
 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* One "DRAM line" contains 64 "DRAM clusters", 1024b total. */
 | 
					 | 
				
			||||||
struct sigma_dram_line {
 | 
					struct sigma_dram_line {
 | 
				
			||||||
	struct sigma_dram_cluster	cluster[64];
 | 
						struct sigma_dram_cluster {
 | 
				
			||||||
};
 | 
							uint16_t timestamp;
 | 
				
			||||||
 | 
							uint16_t samples[EVENTS_PER_CLUSTER];
 | 
				
			||||||
struct clockselect_50 {
 | 
						} cluster[CLUSTERS_PER_ROW];
 | 
				
			||||||
	uint8_t async;
 | 
					 | 
				
			||||||
	uint8_t fraction;
 | 
					 | 
				
			||||||
	uint16_t disabled_channels;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The effect of all these are still a bit unclear. */
 | 
					/* The effect of all these are still a bit unclear. */
 | 
				
			||||||
struct triggerinout {
 | 
					struct triggerinout {
 | 
				
			||||||
	uint8_t trgout_resistor_enable : 1;
 | 
						gboolean trgout_resistor_enable, trgout_resistor_pullup;
 | 
				
			||||||
	uint8_t trgout_resistor_pullup : 1;
 | 
						gboolean trgout_resistor_enable2, trgout_resistor_pullup2;
 | 
				
			||||||
	uint8_t reserved1 : 1;
 | 
						gboolean trgout_bytrigger, trgout_byevent, trgout_bytriggerin;
 | 
				
			||||||
	uint8_t trgout_bytrigger : 1;
 | 
						gboolean trgout_long, trgout_pin; /* 1ms pulse, 1k resistor */
 | 
				
			||||||
	uint8_t trgout_byevent : 1;
 | 
						gboolean trgin_negate, trgout_enable, trgin_enable;
 | 
				
			||||||
	uint8_t trgout_bytriggerin : 1;
 | 
					 | 
				
			||||||
	uint8_t reserved2 : 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Should be set same as the first two */
 | 
					 | 
				
			||||||
	uint8_t trgout_resistor_enable2 : 1;
 | 
					 | 
				
			||||||
	uint8_t trgout_resistor_pullup2 : 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint8_t reserved3 : 1;
 | 
					 | 
				
			||||||
	uint8_t trgout_long : 1;
 | 
					 | 
				
			||||||
	uint8_t trgout_pin : 1; /* Use 1k resistor. Pullup? */
 | 
					 | 
				
			||||||
	uint8_t trgin_negate : 1;
 | 
					 | 
				
			||||||
	uint8_t trgout_enable : 1;
 | 
					 | 
				
			||||||
	uint8_t trgin_enable : 1;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct triggerlut {
 | 
					struct triggerlut {
 | 
				
			||||||
	/* The actual LUTs. */
 | 
					 | 
				
			||||||
	uint16_t m0d[4], m1d[4], m2d[4];
 | 
						uint16_t m0d[4], m1d[4], m2d[4];
 | 
				
			||||||
	uint16_t m3, m3s, m4;
 | 
						uint16_t m3q, m3s, m4;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Parameters should be sent as a single register write. */
 | 
					 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		uint8_t selc : 2;
 | 
							uint8_t selpresc;
 | 
				
			||||||
		uint8_t selpresc : 6;
 | 
							uint8_t sela, selb, selc;
 | 
				
			||||||
 | 
							uint8_t selinc, selres;
 | 
				
			||||||
		uint8_t selinc : 2;
 | 
							uint16_t cmpa, cmpb;
 | 
				
			||||||
		uint8_t selres : 2;
 | 
					 | 
				
			||||||
		uint8_t sela : 2;
 | 
					 | 
				
			||||||
		uint8_t selb : 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		uint16_t cmpb;
 | 
					 | 
				
			||||||
		uint16_t cmpa;
 | 
					 | 
				
			||||||
	} params;
 | 
						} params;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,49 +306,120 @@ enum triggerfunc {
 | 
				
			||||||
	FUNC_NXOR,
 | 
						FUNC_NXOR,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sigma_state {
 | 
					enum sigma_firmware_idx {
 | 
				
			||||||
 | 
						SIGMA_FW_NONE,
 | 
				
			||||||
 | 
						SIGMA_FW_50MHZ,
 | 
				
			||||||
 | 
						SIGMA_FW_100MHZ,
 | 
				
			||||||
 | 
						SIGMA_FW_200MHZ,
 | 
				
			||||||
 | 
						SIGMA_FW_SYNC,
 | 
				
			||||||
 | 
						SIGMA_FW_FREQ,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum ext_clock_edge_t {
 | 
				
			||||||
 | 
						SIGMA_CLOCK_EDGE_RISING,
 | 
				
			||||||
 | 
						SIGMA_CLOCK_EDGE_FALLING,
 | 
				
			||||||
 | 
						SIGMA_CLOCK_EDGE_EITHER,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct submit_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dev_context {
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint16_t vid, pid;
 | 
				
			||||||
 | 
							uint32_t serno;
 | 
				
			||||||
 | 
							uint16_t prefix;
 | 
				
			||||||
 | 
							enum asix_device_type type;
 | 
				
			||||||
 | 
						} id;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							struct ftdi_context ctx;
 | 
				
			||||||
 | 
							gboolean is_open, must_close;
 | 
				
			||||||
 | 
						} ftdi;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							uint64_t samplerate;
 | 
				
			||||||
 | 
							gboolean use_ext_clock;
 | 
				
			||||||
 | 
							size_t clock_pin;
 | 
				
			||||||
 | 
							enum ext_clock_edge_t clock_edge;
 | 
				
			||||||
 | 
						} clock;
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * User specified configuration values, in contrast to
 | 
				
			||||||
 | 
							 * internal arrangement of acquisition, and submission
 | 
				
			||||||
 | 
							 * to the session feed.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							struct sr_sw_limits config;
 | 
				
			||||||
 | 
							struct sr_sw_limits acquire;
 | 
				
			||||||
 | 
							struct sr_sw_limits submit;
 | 
				
			||||||
 | 
						} limit;
 | 
				
			||||||
 | 
						enum sigma_firmware_idx firmware_idx;
 | 
				
			||||||
 | 
						struct sigma_sample_interp {
 | 
				
			||||||
 | 
							/* Interpretation of sample memory. */
 | 
				
			||||||
 | 
							size_t num_channels;
 | 
				
			||||||
 | 
							size_t samples_per_event;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								uint16_t ts;
 | 
				
			||||||
 | 
								uint16_t sample;
 | 
				
			||||||
 | 
							} last;
 | 
				
			||||||
 | 
							struct sigma_location {
 | 
				
			||||||
 | 
								size_t raw, line, cluster, event;
 | 
				
			||||||
 | 
							} start, stop, trig, iter, trig_arm;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								size_t lines_total, lines_done;
 | 
				
			||||||
 | 
								size_t lines_per_read; /* USB transfer limit */
 | 
				
			||||||
 | 
								size_t lines_rcvd;
 | 
				
			||||||
 | 
								struct sigma_dram_line *rcvd_lines;
 | 
				
			||||||
 | 
								struct sigma_dram_line *curr_line;
 | 
				
			||||||
 | 
							} fetch;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								gboolean armed;
 | 
				
			||||||
 | 
								gboolean matched;
 | 
				
			||||||
 | 
								size_t evt_remain;
 | 
				
			||||||
 | 
							} trig_chk;
 | 
				
			||||||
 | 
						} interp;
 | 
				
			||||||
 | 
						uint64_t capture_ratio;
 | 
				
			||||||
 | 
						struct sigma_trigger trigger;
 | 
				
			||||||
 | 
						gboolean use_triggers;
 | 
				
			||||||
 | 
						gboolean late_trigger_timeout;
 | 
				
			||||||
	enum {
 | 
						enum {
 | 
				
			||||||
		SIGMA_UNINITIALIZED = 0,
 | 
							SIGMA_UNINITIALIZED = 0,
 | 
				
			||||||
 | 
							SIGMA_CONFIG,
 | 
				
			||||||
		SIGMA_IDLE,
 | 
							SIGMA_IDLE,
 | 
				
			||||||
		SIGMA_CAPTURE,
 | 
							SIGMA_CAPTURE,
 | 
				
			||||||
 | 
							SIGMA_STOPPING,
 | 
				
			||||||
		SIGMA_DOWNLOAD,
 | 
							SIGMA_DOWNLOAD,
 | 
				
			||||||
	} state;
 | 
						} state;
 | 
				
			||||||
 | 
						struct submit_buffer *buffer;
 | 
				
			||||||
	uint16_t lastts;
 | 
					 | 
				
			||||||
	uint16_t lastsample;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Private, per-device-instance driver context. */
 | 
					/* "Automatic" and forced USB connection open/close support. */
 | 
				
			||||||
struct dev_context {
 | 
					SR_PRIV int sigma_check_open(const struct sr_dev_inst *sdi);
 | 
				
			||||||
	struct ftdi_context ftdic;
 | 
					SR_PRIV int sigma_check_close(struct dev_context *devc);
 | 
				
			||||||
	uint64_t cur_samplerate;
 | 
					SR_PRIV int sigma_force_open(const struct sr_dev_inst *sdi);
 | 
				
			||||||
	uint64_t limit_msec;
 | 
					SR_PRIV int sigma_force_close(struct dev_context *devc);
 | 
				
			||||||
	uint64_t limit_samples;
 | 
					 | 
				
			||||||
	uint64_t sent_samples;
 | 
					 | 
				
			||||||
	uint64_t start_time;
 | 
					 | 
				
			||||||
	int cur_firmware;
 | 
					 | 
				
			||||||
	int num_channels;
 | 
					 | 
				
			||||||
	int cur_channels;
 | 
					 | 
				
			||||||
	int samples_per_event;
 | 
					 | 
				
			||||||
	int capture_ratio;
 | 
					 | 
				
			||||||
	struct sigma_trigger trigger;
 | 
					 | 
				
			||||||
	int use_triggers;
 | 
					 | 
				
			||||||
	struct sigma_state state;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern SR_PRIV const uint64_t samplerates[];
 | 
					/* Save configuration across sessions, to reduce cost of continuation. */
 | 
				
			||||||
extern SR_PRIV const size_t samplerates_count;
 | 
					SR_PRIV int sigma_store_hw_config(const struct sr_dev_inst *sdi);
 | 
				
			||||||
 | 
					SR_PRIV int sigma_fetch_hw_config(const struct sr_dev_inst *sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int sigma_write_register(uint8_t reg, uint8_t *data, size_t len,
 | 
					/* Send register content (simple and complex) to the hardware. */
 | 
				
			||||||
				 struct dev_context *devc);
 | 
					SR_PRIV int sigma_write_register(struct dev_context *devc,
 | 
				
			||||||
SR_PRIV int sigma_set_register(uint8_t reg, uint8_t value, struct dev_context *devc);
 | 
						uint8_t reg, uint8_t *data, size_t len);
 | 
				
			||||||
SR_PRIV int sigma_write_trigger_lut(struct triggerlut *lut, struct dev_context *devc);
 | 
					SR_PRIV int sigma_set_register(struct dev_context *devc,
 | 
				
			||||||
SR_PRIV void sigma_clear_helper(void *priv);
 | 
						uint8_t reg, uint8_t value);
 | 
				
			||||||
SR_PRIV uint64_t sigma_limit_samples_to_msec(const struct dev_context *devc,
 | 
					SR_PRIV int sigma_write_trigger_lut(struct dev_context *devc,
 | 
				
			||||||
					     uint64_t limit_samples);
 | 
						struct triggerlut *lut);
 | 
				
			||||||
SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi, uint64_t samplerate);
 | 
					
 | 
				
			||||||
 | 
					/* Samplerate constraints check, get/set/list helpers. */
 | 
				
			||||||
 | 
					SR_PRIV int sigma_normalize_samplerate(uint64_t want_rate, uint64_t *have_rate);
 | 
				
			||||||
 | 
					SR_PRIV GVariant *sigma_get_samplerates_list(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Preparation of data acquisition, spec conversion, hardware configuration. */
 | 
				
			||||||
 | 
					SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi);
 | 
				
			||||||
 | 
					SR_PRIV int sigma_set_acquire_timeout(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi);
 | 
					SR_PRIV int sigma_convert_trigger(const struct sr_dev_inst *sdi);
 | 
				
			||||||
 | 
					SR_PRIV int sigma_build_basic_trigger(struct dev_context *devc,
 | 
				
			||||||
 | 
						struct triggerlut *lut);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Callback to periodically drive acuisition progress. */
 | 
				
			||||||
SR_PRIV int sigma_receive_data(int fd, int revents, void *cb_data);
 | 
					SR_PRIV int sigma_receive_data(int fd, int revents, void *cb_data);
 | 
				
			||||||
SR_PRIV int sigma_build_basic_trigger(struct triggerlut *lut, struct dev_context *devc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,8 +113,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options, int modelid)
 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
						if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* This is how the vendor software scans for hardware. */
 | 
						/* This is how the vendor software scans for hardware. */
 | 
				
			||||||
	memset(packet, 0, PACKET_SIZE);
 | 
						memset(packet, 0, PACKET_SIZE);
 | 
				
			||||||
	packet[0] = 0xaa;
 | 
						packet[0] = 0xaa;
 | 
				
			||||||
| 
						 | 
					@ -182,21 +180,19 @@ static GSList *scan_3203(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	return scan(di, options, PPS_3203T_3S);
 | 
						return scan(di, options, PPS_3203T_3S);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_channel *ch;
 | 
						struct sr_channel *ch;
 | 
				
			||||||
	int channel, ret;
 | 
						int channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sdi)
 | 
						if (!sdi)
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	if (!cg) {
 | 
						if (!cg) {
 | 
				
			||||||
		/* No channel group: global options. */
 | 
					 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
		case SR_CONF_CHANNEL_CONFIG:
 | 
							case SR_CONF_CHANNEL_CONFIG:
 | 
				
			||||||
			*data = g_variant_new_string(channel_modes[devc->channel_mode]);
 | 
								*data = g_variant_new_string(channel_modes[devc->channel_mode]);
 | 
				
			||||||
| 
						 | 
					@ -233,64 +229,36 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int find_str(const char *str, const char **strings, int array_size)
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
{
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
	int idx, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idx = -1;
 | 
					 | 
				
			||||||
	for (i = 0; i < array_size; i++) {
 | 
					 | 
				
			||||||
		if (!strcmp(str, strings[i])) {
 | 
					 | 
				
			||||||
			idx = i;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return idx;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_channel *ch;
 | 
						struct sr_channel *ch;
 | 
				
			||||||
	gdouble dval;
 | 
						gdouble dval;
 | 
				
			||||||
	int channel, ret, ival;
 | 
						int channel, ival;
 | 
				
			||||||
	const char *sval;
 | 
					 | 
				
			||||||
	gboolean bval;
 | 
						gboolean bval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cg) {
 | 
						if (!cg) {
 | 
				
			||||||
		/* No channel group: global options. */
 | 
					 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
		case SR_CONF_CHANNEL_CONFIG:
 | 
							case SR_CONF_CHANNEL_CONFIG:
 | 
				
			||||||
			sval = g_variant_get_string(data, NULL);
 | 
								if ((ival = std_str_idx(data, ARRAY_AND_SIZE(channel_modes))) < 0)
 | 
				
			||||||
			if ((ival = find_str(sval, channel_modes,
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
							ARRAY_SIZE(channel_modes))) == -1) {
 | 
								if (devc->model->channel_modes && (1 << ival) == 0)
 | 
				
			||||||
				ret = SR_ERR_ARG;
 | 
									return SR_ERR_ARG; /* Not supported on this model. */
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (devc->model->channel_modes && (1 << ival) == 0) {
 | 
					 | 
				
			||||||
				/* Not supported on this model. */
 | 
					 | 
				
			||||||
				ret = SR_ERR_ARG;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (ival == devc->channel_mode_set)
 | 
								if (ival == devc->channel_mode_set)
 | 
				
			||||||
				/* Nothing to do. */
 | 
									break; /* Nothing to do. */
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			devc->channel_mode_set = ival;
 | 
								devc->channel_mode_set = ival;
 | 
				
			||||||
			devc->config_dirty = TRUE;
 | 
								devc->config_dirty = TRUE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
 | 
							case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
 | 
				
			||||||
			bval = g_variant_get_boolean(data);
 | 
								bval = g_variant_get_boolean(data);
 | 
				
			||||||
			if (bval == devc->over_current_protection_set)
 | 
								if (bval == devc->over_current_protection_set)
 | 
				
			||||||
				/* Nothing to do. */
 | 
									break; /* Nothing to do. */
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			devc->over_current_protection_set = bval;
 | 
								devc->over_current_protection_set = bval;
 | 
				
			||||||
			devc->config_dirty = TRUE;
 | 
								devc->config_dirty = TRUE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -298,7 +266,6 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/* Channel group specified: per-channel options. */
 | 
					 | 
				
			||||||
		/* We only ever have one channel per channel group in this driver. */
 | 
							/* We only ever have one channel per channel group in this driver. */
 | 
				
			||||||
		ch = cg->channels->data;
 | 
							ch = cg->channels->data;
 | 
				
			||||||
		channel = ch->index;
 | 
							channel = ch->index;
 | 
				
			||||||
| 
						 | 
					@ -307,116 +274,85 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
		case SR_CONF_VOLTAGE_TARGET:
 | 
							case SR_CONF_VOLTAGE_TARGET:
 | 
				
			||||||
			dval = g_variant_get_double(data);
 | 
								dval = g_variant_get_double(data);
 | 
				
			||||||
			if (dval < 0 || dval > devc->model->channels[channel].voltage[1])
 | 
								if (dval < 0 || dval > devc->model->channels[channel].voltage[1])
 | 
				
			||||||
				ret = SR_ERR_ARG;
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
			devc->config[channel].output_voltage_max = dval;
 | 
								devc->config[channel].output_voltage_max = dval;
 | 
				
			||||||
			devc->config_dirty = TRUE;
 | 
								devc->config_dirty = TRUE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_CURRENT_LIMIT:
 | 
							case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
			dval = g_variant_get_double(data);
 | 
								dval = g_variant_get_double(data);
 | 
				
			||||||
			if (dval < 0 || dval > devc->model->channels[channel].current[1])
 | 
								if (dval < 0 || dval > devc->model->channels[channel].current[1])
 | 
				
			||||||
				ret = SR_ERR_ARG;
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
			devc->config[channel].output_current_max = dval;
 | 
								devc->config[channel].output_current_max = dval;
 | 
				
			||||||
			devc->config_dirty = TRUE;
 | 
								devc->config_dirty = TRUE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_ENABLED:
 | 
							case SR_CONF_ENABLED:
 | 
				
			||||||
			bval = g_variant_get_boolean(data);
 | 
								bval = g_variant_get_boolean(data);
 | 
				
			||||||
			if (bval == devc->config[channel].output_enabled_set)
 | 
								if (bval == devc->config[channel].output_enabled_set)
 | 
				
			||||||
				/* Nothing to do. */
 | 
									break; /* Nothing to do. */
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			devc->config[channel].output_enabled_set = bval;
 | 
								devc->config[channel].output_enabled_set = bval;
 | 
				
			||||||
			devc->config_dirty = TRUE;
 | 
								devc->config_dirty = TRUE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			ret = SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_channel *ch;
 | 
						struct sr_channel *ch;
 | 
				
			||||||
	GVariant *gvar;
 | 
						int channel;
 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
	int channel, ret, i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Always available. */
 | 
						devc = (sdi) ? sdi->priv : NULL;
 | 
				
			||||||
	if (key == SR_CONF_SCAN_OPTIONS) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sdi)
 | 
					 | 
				
			||||||
		return SR_ERR_ARG;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	if (!cg) {
 | 
						if (!cg) {
 | 
				
			||||||
		/* No channel group: global options. */
 | 
					 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
 | 
							case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
							case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SR_CONF_CHANNEL_CONFIG:
 | 
							case SR_CONF_CHANNEL_CONFIG:
 | 
				
			||||||
 | 
								if (!devc || !devc->model)
 | 
				
			||||||
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
			if (devc->model->channel_modes == CHANMODE_INDEPENDENT) {
 | 
								if (devc->model->channel_modes == CHANMODE_INDEPENDENT) {
 | 
				
			||||||
				/* The 1-channel models. */
 | 
									/* The 1-channel models. */
 | 
				
			||||||
				*data = g_variant_new_strv(channel_modes, 1);
 | 
									*data = g_variant_new_strv(channel_modes, 1);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				/* The other models support all modes. */
 | 
									/* The other models support all modes. */
 | 
				
			||||||
				*data = g_variant_new_strv(channel_modes, ARRAY_SIZE(channel_modes));
 | 
									*data = g_variant_new_strv(ARRAY_AND_SIZE(channel_modes));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		/* Channel group specified: per-channel options. */
 | 
					 | 
				
			||||||
		if (!sdi)
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
					 | 
				
			||||||
		/* We only ever have one channel per channel group in this driver. */
 | 
							/* We only ever have one channel per channel group in this driver. */
 | 
				
			||||||
		ch = cg->channels->data;
 | 
							ch = cg->channels->data;
 | 
				
			||||||
		channel = ch->index;
 | 
							channel = ch->index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
							case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								*data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg));
 | 
				
			||||||
					devopts_cg, ARRAY_SIZE(devopts_cg), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_VOLTAGE_TARGET:
 | 
							case SR_CONF_VOLTAGE_TARGET:
 | 
				
			||||||
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
 | 
								if (!devc || !devc->model)
 | 
				
			||||||
			/* Min, max, step. */
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
			for (i = 0; i < 3; i++) {
 | 
								*data = std_gvar_min_max_step_array(devc->model->channels[channel].voltage);
 | 
				
			||||||
				gvar = g_variant_new_double(devc->model->channels[channel].voltage[i]);
 | 
					 | 
				
			||||||
				g_variant_builder_add_value(&gvb, gvar);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case SR_CONF_CURRENT_LIMIT:
 | 
							case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
 | 
								if (!devc || !devc->model)
 | 
				
			||||||
			/* Min, max, step. */
 | 
									return SR_ERR_ARG;
 | 
				
			||||||
			for (i = 0; i < 3; i++) {
 | 
								*data = std_gvar_min_max_step_array(devc->model->channels[channel].current);
 | 
				
			||||||
				gvar = g_variant_new_double(devc->model->channels[channel].current[i]);
 | 
					 | 
				
			||||||
				g_variant_builder_add_value(&gvb, gvar);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_close(struct sr_dev_inst *sdi)
 | 
					static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -424,6 +360,7 @@ static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (devc->config_dirty)
 | 
						if (devc->config_dirty)
 | 
				
			||||||
		/* Some configuration changes were queued up but didn't
 | 
							/* Some configuration changes were queued up but didn't
 | 
				
			||||||
		 * get sent to the device, likely because we were never
 | 
							 * get sent to the device, likely because we were never
 | 
				
			||||||
| 
						 | 
					@ -439,9 +376,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
	uint8_t packet[PACKET_SIZE];
 | 
						uint8_t packet[PACKET_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	memset(devc->packet, 0x44, PACKET_SIZE);
 | 
						memset(devc->packet, 0x44, PACKET_SIZE);
 | 
				
			||||||
	devc->packet_size = 0;
 | 
						devc->packet_size = 0;
 | 
				
			||||||
| 
						 | 
					@ -466,9 +400,6 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	devc->acquisition_running = FALSE;
 | 
						devc->acquisition_running = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -483,7 +414,7 @@ static struct sr_dev_driver atten_pps3203_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan_3203,
 | 
						.scan = scan_3203,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,15 +71,11 @@ struct per_channel_config {
 | 
				
			||||||
	gboolean output_enabled_set;
 | 
						gboolean output_enabled_set;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	/* Model-specific information */
 | 
					 | 
				
			||||||
	const struct pps_model *model;
 | 
						const struct pps_model *model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Acquisition state */
 | 
					 | 
				
			||||||
	gboolean acquisition_running;
 | 
						gboolean acquisition_running;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Operational state */
 | 
					 | 
				
			||||||
	gboolean config_dirty;
 | 
						gboolean config_dirty;
 | 
				
			||||||
	struct per_channel_config *config;
 | 
						struct per_channel_config *config;
 | 
				
			||||||
	/* Blocking write timeout for packet. */
 | 
						/* Blocking write timeout for packet. */
 | 
				
			||||||
| 
						 | 
					@ -91,7 +87,6 @@ struct dev_context {
 | 
				
			||||||
	int channel_mode_set;
 | 
						int channel_mode_set;
 | 
				
			||||||
	gboolean over_current_protection_set;
 | 
						gboolean over_current_protection_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Temporary state across callbacks */
 | 
					 | 
				
			||||||
	uint8_t packet[PACKET_SIZE];
 | 
						uint8_t packet[PACKET_SIZE];
 | 
				
			||||||
	int packet_size;
 | 
						int packet_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,11 @@
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
#include <sys/timerfd.h>
 | 
					#include <sys/timerfd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
 | 
						SR_CONF_THERMOMETER,
 | 
				
			||||||
 | 
						SR_CONF_POWERMETER,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
	SR_CONF_CONTINUOUS,
 | 
						SR_CONF_CONTINUOUS,
 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
| 
						 | 
					@ -126,27 +131,8 @@ err_out:
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_open(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_ACTIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_close(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		      const struct sr_dev_inst *sdi,
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
		      const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -156,11 +142,11 @@ static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
						ret = SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		ret = sr_sw_limits_config_get(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_get(&devc->limits, key, data);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->samplerate);
 | 
							*data = g_variant_new_uint64(devc->samplerate);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -186,30 +172,22 @@ static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		      const struct sr_dev_inst *sdi,
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
		      const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	uint64_t samplerate;
 | 
						uint64_t samplerate;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		ret = sr_sw_limits_config_set(&devc->limits, key, data);
 | 
							return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		samplerate = g_variant_get_uint64(data);
 | 
							samplerate = g_variant_get_uint64(data);
 | 
				
			||||||
		if (samplerate > MAX_SAMPLE_RATE) {
 | 
							if (samplerate > MAX_SAMPLE_RATE) {
 | 
				
			||||||
			sr_err("Maximum sample rate is %d", MAX_SAMPLE_RATE);
 | 
								sr_err("Maximum sample rate is %d", MAX_SAMPLE_RATE);
 | 
				
			||||||
			ret = SR_ERR_SAMPLERATE;
 | 
								return SR_ERR_SAMPLERATE;
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		devc->samplerate = samplerate;
 | 
							devc->samplerate = samplerate;
 | 
				
			||||||
		bl_acme_maybe_set_update_interval(sdi, samplerate);
 | 
							bl_acme_maybe_set_update_interval(sdi, samplerate);
 | 
				
			||||||
| 
						 | 
					@ -217,46 +195,30 @@ static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
	case SR_CONF_PROBE_FACTOR:
 | 
						case SR_CONF_PROBE_FACTOR:
 | 
				
			||||||
		if (!cg)
 | 
							if (!cg)
 | 
				
			||||||
			return SR_ERR_CHANNEL_GROUP;
 | 
								return SR_ERR_CHANNEL_GROUP;
 | 
				
			||||||
		ret = bl_acme_set_shunt(cg, g_variant_get_uint64(data));
 | 
							return bl_acme_set_shunt(cg, g_variant_get_uint64(data));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_POWER_OFF:
 | 
						case SR_CONF_POWER_OFF:
 | 
				
			||||||
		if (!cg)
 | 
							if (!cg)
 | 
				
			||||||
			return SR_ERR_CHANNEL_GROUP;
 | 
								return SR_ERR_CHANNEL_GROUP;
 | 
				
			||||||
		ret = bl_acme_set_power_off(cg, g_variant_get_boolean(data));
 | 
							return bl_acme_set_power_off(cg, g_variant_get_boolean(data));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		       const struct sr_dev_inst *sdi,
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
		       const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t devopts_cg[MAX_DEVOPTS_CG];
 | 
						uint32_t devopts_cg[MAX_DEVOPTS_CG];
 | 
				
			||||||
	GVariant *gvar;
 | 
						int num_devopts_cg = 0;
 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
	int ret, num_devopts_cg = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	if (!cg) {
 | 
						if (!cg) {
 | 
				
			||||||
		switch (key) {
 | 
							switch (key) {
 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
							case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								return STD_CONFIG_LIST(key, data, sdi, cg, NO_OPTS, drvopts, devopts);
 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SR_CONF_SAMPLERATE:
 | 
							case SR_CONF_SAMPLERATE:
 | 
				
			||||||
			g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
 | 
								*data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
 | 
				
			||||||
			gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
 | 
					 | 
				
			||||||
				samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
 | 
					 | 
				
			||||||
			g_variant_builder_add(&gvb, "{sv}",
 | 
					 | 
				
			||||||
					      "samplerate-steps", gvar);
 | 
					 | 
				
			||||||
			*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
| 
						 | 
					@ -269,15 +231,14 @@ static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
			if (bl_acme_probe_has_pws(cg))
 | 
								if (bl_acme_probe_has_pws(cg))
 | 
				
			||||||
				devopts_cg[num_devopts_cg++] = HAS_POWER_OFF;
 | 
									devopts_cg[num_devopts_cg++] = HAS_POWER_OFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
								*data = std_gvar_array_u32(devopts_cg, num_devopts_cg);
 | 
				
			||||||
				devopts_cg, num_devopts_cg, sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return SR_ERR_NA;
 | 
								return SR_ERR_NA;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dev_acquisition_close(const struct sr_dev_inst *sdi)
 | 
					static void dev_acquisition_close(const struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -316,9 +277,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
		.it_value = { 0, 0 }
 | 
							.it_value = { 0, 0 }
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (dev_acquisition_open(sdi))
 | 
						if (dev_acquisition_open(sdi))
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,9 +318,6 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dev_acquisition_close(sdi);
 | 
						dev_acquisition_close(sdi);
 | 
				
			||||||
	sr_session_source_remove_channel(sdi->session, devc->channel);
 | 
						sr_session_source_remove_channel(sdi->session, devc->channel);
 | 
				
			||||||
	g_io_channel_shutdown(devc->channel, FALSE, NULL);
 | 
						g_io_channel_shutdown(devc->channel, FALSE, NULL);
 | 
				
			||||||
| 
						 | 
					@ -385,11 +340,12 @@ static struct sr_dev_driver baylibre_acme_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
	.dev_open = dev_open,
 | 
						.dev_open = std_dummy_dev_open,
 | 
				
			||||||
	.dev_close = dev_close,
 | 
						.dev_close = std_dummy_dev_close,
 | 
				
			||||||
	.dev_acquisition_start = dev_acquisition_start,
 | 
						.dev_acquisition_start = dev_acquisition_start,
 | 
				
			||||||
	.dev_acquisition_stop = dev_acquisition_stop,
 | 
						.dev_acquisition_stop = dev_acquisition_stop,
 | 
				
			||||||
	.context = NULL,
 | 
						.context = NULL,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,8 +166,10 @@ SR_PRIV gboolean bl_acme_detect_probe(unsigned int addr,
 | 
				
			||||||
	probe_name_path(addr, path);
 | 
						probe_name_path(addr, path);
 | 
				
			||||||
	status = g_file_get_contents(path->str, &buf, &size, &err);
 | 
						status = g_file_get_contents(path->str, &buf, &size, &err);
 | 
				
			||||||
	if (!status) {
 | 
						if (!status) {
 | 
				
			||||||
		sr_dbg("Name for probe %d can't be read: %s",
 | 
							/* Don't log "No such file or directory" messages. */
 | 
				
			||||||
		       prb_num, err->message);
 | 
							if (err->code != G_FILE_ERROR_NOENT)
 | 
				
			||||||
 | 
								sr_dbg("Name for probe %d can't be read (%d): %s",
 | 
				
			||||||
 | 
								       prb_num, err->code, err->message);
 | 
				
			||||||
		g_string_free(path, TRUE);
 | 
							g_string_free(path, TRUE);
 | 
				
			||||||
		g_error_free(err);
 | 
							g_error_free(err);
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
| 
						 | 
					@ -701,7 +703,7 @@ SR_PRIV void bl_acme_close_channel(struct sr_channel *ch)
 | 
				
			||||||
SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
 | 
					SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint64_t nrexpiration;
 | 
						uint64_t nrexpiration;
 | 
				
			||||||
	struct sr_datafeed_packet packet, framep;
 | 
						struct sr_datafeed_packet packet;
 | 
				
			||||||
	struct sr_datafeed_analog analog;
 | 
						struct sr_datafeed_analog analog;
 | 
				
			||||||
	struct sr_analog_encoding encoding;
 | 
						struct sr_analog_encoding encoding;
 | 
				
			||||||
	struct sr_analog_meaning meaning;
 | 
						struct sr_analog_meaning meaning;
 | 
				
			||||||
| 
						 | 
					@ -757,8 +759,7 @@ SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	 * accuracy.
 | 
						 * accuracy.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	for (i = 0; i < nrexpiration; i++) {
 | 
						for (i = 0; i < nrexpiration; i++) {
 | 
				
			||||||
		framep.type = SR_DF_FRAME_BEGIN;
 | 
							std_session_send_df_frame_begin(sdi);
 | 
				
			||||||
		sr_session_send(sdi, &framep);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Due to different units used in each channel we're sending
 | 
							 * Due to different units used in each channel we're sending
 | 
				
			||||||
| 
						 | 
					@ -786,14 +787,13 @@ SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
			sr_session_send(sdi, &packet);
 | 
								sr_session_send(sdi, &packet);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		framep.type = SR_DF_FRAME_END;
 | 
							std_session_send_df_frame_end(sdi);
 | 
				
			||||||
		sr_session_send(sdi, &framep);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
						sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->limits)) {
 | 
						if (sr_sw_limits_check(&devc->limits)) {
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
		return TRUE;
 | 
							return TRUE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,6 @@ enum probe_type {
 | 
				
			||||||
	PROBE_TEMP,
 | 
						PROBE_TEMP,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	uint64_t samplerate;
 | 
						uint64_t samplerate;
 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
						struct sr_sw_limits limits;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2014 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
					 * Copyright (C) 2014-2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -21,24 +21,25 @@
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
#include "beaglelogic.h"
 | 
					#include "beaglelogic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Scan options */
 | 
					 | 
				
			||||||
static const uint32_t scanopts[] = {
 | 
					static const uint32_t scanopts[] = {
 | 
				
			||||||
 | 
						SR_CONF_CONN,
 | 
				
			||||||
	SR_CONF_NUM_LOGIC_CHANNELS,
 | 
						SR_CONF_NUM_LOGIC_CHANNELS,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Hardware capabilities */
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_LOGIC_ANALYZER,
 | 
						SR_CONF_LOGIC_ANALYZER,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
	SR_CONF_CONTINUOUS,
 | 
						SR_CONF_CONTINUOUS,
 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
 | 
						SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
 | 
						SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_NUM_LOGIC_CHANNELS | SR_CONF_GET,
 | 
						SR_CONF_NUM_LOGIC_CHANNELS | SR_CONF_GET,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Trigger matching capabilities */
 | 
					static const int32_t trigger_matches[] = {
 | 
				
			||||||
static const int32_t soft_trigger_matches[] = {
 | 
					 | 
				
			||||||
	SR_TRIGGER_ZERO,
 | 
						SR_TRIGGER_ZERO,
 | 
				
			||||||
	SR_TRIGGER_ONE,
 | 
						SR_TRIGGER_ONE,
 | 
				
			||||||
	SR_TRIGGER_RISING,
 | 
						SR_TRIGGER_RISING,
 | 
				
			||||||
| 
						 | 
					@ -58,67 +59,78 @@ static const uint64_t samplerates[] = {
 | 
				
			||||||
	SR_HZ(1),
 | 
						SR_HZ(1),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dev_context *beaglelogic_devc_alloc(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = g_malloc0(sizeof(struct dev_context));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Default non-zero values (if any) */
 | 
					 | 
				
			||||||
	devc->fd = -1;
 | 
					 | 
				
			||||||
	devc->limit_samples = (uint64_t)-1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return devc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GSList *l;
 | 
						GSList *l;
 | 
				
			||||||
	struct sr_config *src;
 | 
						struct sr_config *src;
 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
						struct sr_dev_inst *sdi;
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						const char *conn;
 | 
				
			||||||
 | 
						gchar **params;
 | 
				
			||||||
	int i, maxch;
 | 
						int i, maxch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Probe for /dev/beaglelogic */
 | 
						maxch = NUM_CHANNELS;
 | 
				
			||||||
	if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS))
 | 
						conn = NULL;
 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
	sdi->model = g_strdup("BeagleLogic");
 | 
					 | 
				
			||||||
	sdi->version = g_strdup("1.0");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Unless explicitly specified, keep max channels to 8 only */
 | 
					 | 
				
			||||||
	maxch = 8;
 | 
					 | 
				
			||||||
	for (l = options; l; l = l->next) {
 | 
						for (l = options; l; l = l->next) {
 | 
				
			||||||
		src = l->data;
 | 
							src = l->data;
 | 
				
			||||||
		if (src->key == SR_CONF_NUM_LOGIC_CHANNELS)
 | 
							if (src->key == SR_CONF_NUM_LOGIC_CHANNELS)
 | 
				
			||||||
			maxch = g_variant_get_int32(src->data);
 | 
								maxch = g_variant_get_int32(src->data);
 | 
				
			||||||
 | 
							if (src->key == SR_CONF_CONN)
 | 
				
			||||||
 | 
								conn = g_variant_get_string(src->data, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We need to test for number of channels by opening the node */
 | 
						/* Probe for /dev/beaglelogic if not connecting via TCP */
 | 
				
			||||||
	devc = beaglelogic_devc_alloc();
 | 
						if (!conn) {
 | 
				
			||||||
 | 
							params = NULL;
 | 
				
			||||||
	if (beaglelogic_open_nonblock(devc) != SR_OK) {
 | 
							if (!g_file_test(BEAGLELOGIC_DEV_NODE, G_FILE_TEST_EXISTS))
 | 
				
			||||||
		g_free(devc);
 | 
								return NULL;
 | 
				
			||||||
		sr_dev_inst_free(sdi);
 | 
						} else {
 | 
				
			||||||
 | 
							params = g_strsplit(conn, "/", 0);
 | 
				
			||||||
 | 
							if (!params || !params[1] || !params[2]) {
 | 
				
			||||||
 | 
								sr_err("Invalid Parameters.");
 | 
				
			||||||
 | 
								g_strfreev(params);
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (g_ascii_strncasecmp(params[0], "tcp", 3)) {
 | 
				
			||||||
 | 
								sr_err("Only TCP (tcp-raw) protocol is currently supported.");
 | 
				
			||||||
 | 
								g_strfreev(params);
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (maxch > 8) {
 | 
					 | 
				
			||||||
		maxch = NUM_CHANNELS;
 | 
					 | 
				
			||||||
		devc->sampleunit = BL_SAMPLEUNIT_16_BITS;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		maxch = 8;
 | 
					 | 
				
			||||||
		devc->sampleunit = BL_SAMPLEUNIT_8_BITS;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	beaglelogic_set_sampleunit(devc);
 | 
						maxch = (maxch > 8) ? NUM_CHANNELS : 8;
 | 
				
			||||||
	beaglelogic_close(devc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Signal */
 | 
						sdi = g_new0(struct sr_dev_inst, 1);
 | 
				
			||||||
 | 
						sdi->status = SR_ST_INACTIVE;
 | 
				
			||||||
 | 
						sdi->model = g_strdup("BeagleLogic");
 | 
				
			||||||
 | 
						sdi->version = g_strdup("1.0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc = g_malloc0(sizeof(struct dev_context));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Default non-zero values (if any) */
 | 
				
			||||||
 | 
						devc->fd = -1;
 | 
				
			||||||
 | 
						devc->limit_samples = 10000000;
 | 
				
			||||||
 | 
						devc->tcp_buffer = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!conn) {
 | 
				
			||||||
 | 
							devc->beaglelogic = &beaglelogic_native_ops;
 | 
				
			||||||
		sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE);
 | 
							sr_info("BeagleLogic device found at "BEAGLELOGIC_DEV_NODE);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							devc->read_timeout = 1000 * 1000;
 | 
				
			||||||
 | 
							devc->beaglelogic = &beaglelogic_tcp_ops;
 | 
				
			||||||
 | 
							devc->address = g_strdup(params[1]);
 | 
				
			||||||
 | 
							devc->port = g_strdup(params[2]);
 | 
				
			||||||
 | 
							g_strfreev(params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (devc->beaglelogic->open(devc) != SR_OK)
 | 
				
			||||||
 | 
								goto err_free;
 | 
				
			||||||
 | 
							if (beaglelogic_tcp_detect(devc) != SR_OK)
 | 
				
			||||||
 | 
								goto err_free;
 | 
				
			||||||
 | 
							if (devc->beaglelogic->close(devc) != SR_OK)
 | 
				
			||||||
 | 
								goto err_free;
 | 
				
			||||||
 | 
							sr_info("BeagleLogic device found at %s : %s",
 | 
				
			||||||
 | 
								devc->address, devc->port);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Fill the channels */
 | 
						/* Fill the channels */
 | 
				
			||||||
	for (i = 0; i < maxch; i++)
 | 
						for (i = 0; i < maxch; i++)
 | 
				
			||||||
| 
						 | 
					@ -128,6 +140,16 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	sdi->priv = devc;
 | 
						sdi->priv = devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
						return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_free:
 | 
				
			||||||
 | 
						g_free(sdi->model);
 | 
				
			||||||
 | 
						g_free(sdi->version);
 | 
				
			||||||
 | 
						g_free(devc->address);
 | 
				
			||||||
 | 
						g_free(devc->port);
 | 
				
			||||||
 | 
						g_free(devc);
 | 
				
			||||||
 | 
						g_free(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_open(struct sr_dev_inst *sdi)
 | 
					static int dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -135,30 +157,39 @@ static int dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Open BeagleLogic */
 | 
						/* Open BeagleLogic */
 | 
				
			||||||
	if (beaglelogic_open_nonblock(devc))
 | 
						if (devc->beaglelogic->open(devc))
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set fd and local attributes */
 | 
						/* Set fd and local attributes */
 | 
				
			||||||
 | 
						if (devc->beaglelogic == &beaglelogic_tcp_ops)
 | 
				
			||||||
 | 
							devc->pollfd.fd = devc->socket;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		devc->pollfd.fd = devc->fd;
 | 
							devc->pollfd.fd = devc->fd;
 | 
				
			||||||
	devc->pollfd.events = G_IO_IN;
 | 
						devc->pollfd.events = G_IO_IN;
 | 
				
			||||||
	devc->pollfd.revents = 0;
 | 
						devc->pollfd.revents = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the default attributes */
 | 
						/* Get the default attributes */
 | 
				
			||||||
	beaglelogic_get_samplerate(devc);
 | 
						devc->beaglelogic->get_samplerate(devc);
 | 
				
			||||||
	beaglelogic_get_sampleunit(devc);
 | 
						devc->beaglelogic->get_sampleunit(devc);
 | 
				
			||||||
	beaglelogic_get_triggerflags(devc);
 | 
						devc->beaglelogic->get_buffersize(devc);
 | 
				
			||||||
	beaglelogic_get_buffersize(devc);
 | 
						devc->beaglelogic->get_bufunitsize(devc);
 | 
				
			||||||
	beaglelogic_get_bufunitsize(devc);
 | 
					
 | 
				
			||||||
 | 
						/* Set the triggerflags to default for continuous capture unless we
 | 
				
			||||||
 | 
						 * explicitly limit samples using SR_CONF_LIMIT_SAMPLES */
 | 
				
			||||||
 | 
						devc->triggerflags = BL_TRIGGERFLAGS_CONTINUOUS;
 | 
				
			||||||
 | 
						devc->beaglelogic->set_triggerflags(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Map the kernel capture FIFO for reads, saves 1 level of memcpy */
 | 
						/* Map the kernel capture FIFO for reads, saves 1 level of memcpy */
 | 
				
			||||||
	if (beaglelogic_mmap(devc) != SR_OK) {
 | 
						if (devc->beaglelogic == &beaglelogic_native_ops) {
 | 
				
			||||||
 | 
							if (devc->beaglelogic->mmap(devc) != SR_OK) {
 | 
				
			||||||
			sr_err("Unable to map capture buffer");
 | 
								sr_err("Unable to map capture buffer");
 | 
				
			||||||
		beaglelogic_close(devc);
 | 
								devc->beaglelogic->close(devc);
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							devc->tcp_buffer = g_malloc(TCP_BUFFER_SIZE);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* We're good to go now */
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_ACTIVE;
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -166,17 +197,28 @@ static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status == SR_ST_ACTIVE) {
 | 
					 | 
				
			||||||
	/* Close the memory mapping and the file */
 | 
						/* Close the memory mapping and the file */
 | 
				
			||||||
		beaglelogic_munmap(devc);
 | 
						if (devc->beaglelogic == &beaglelogic_native_ops)
 | 
				
			||||||
		beaglelogic_close(devc);
 | 
							devc->beaglelogic->munmap(devc);
 | 
				
			||||||
	}
 | 
						devc->beaglelogic->close(devc);
 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static void clear_helper(struct dev_context *devc)
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					{
 | 
				
			||||||
 | 
						g_free(devc->tcp_buffer);
 | 
				
			||||||
 | 
						g_free(devc->address);
 | 
				
			||||||
 | 
						g_free(devc->port);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dev_clear(const struct sr_dev_driver *di)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,21 +244,18 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
	uint64_t tmp_u64;
 | 
						uint64_t tmp_u64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		devc->cur_samplerate = g_variant_get_uint64(data);
 | 
							devc->cur_samplerate = g_variant_get_uint64(data);
 | 
				
			||||||
		return beaglelogic_set_samplerate(devc);
 | 
							return devc->beaglelogic->set_samplerate(devc);
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		tmp_u64 = g_variant_get_uint64(data);
 | 
							tmp_u64 = g_variant_get_uint64(data);
 | 
				
			||||||
		devc->limit_samples = tmp_u64;
 | 
							devc->limit_samples = tmp_u64;
 | 
				
			||||||
| 
						 | 
					@ -228,17 +267,15 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
			sr_warn("Insufficient buffer space has been allocated.");
 | 
								sr_warn("Insufficient buffer space has been allocated.");
 | 
				
			||||||
			sr_warn("Please use \'echo <size in bytes> > "\
 | 
								sr_warn("Please use \'echo <size in bytes> > "\
 | 
				
			||||||
				BEAGLELOGIC_SYSFS_ATTR(memalloc) \
 | 
									BEAGLELOGIC_SYSFS_ATTR(memalloc) \
 | 
				
			||||||
				"\' as root to increase the buffer size, this"\
 | 
									"\' to increase the buffer size, this"\
 | 
				
			||||||
				" capture is now truncated to %d Msamples",
 | 
									" capture is now truncated to %d Msamples",
 | 
				
			||||||
				devc->buffersize /
 | 
									devc->buffersize /
 | 
				
			||||||
				(SAMPLEUNIT_TO_BYTES(devc->sampleunit) * 1000000));
 | 
									(SAMPLEUNIT_TO_BYTES(devc->sampleunit) * 1000000));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return beaglelogic_set_triggerflags(devc);
 | 
							return devc->beaglelogic->set_triggerflags(devc);
 | 
				
			||||||
	case SR_CONF_CAPTURE_RATIO:
 | 
						case SR_CONF_CAPTURE_RATIO:
 | 
				
			||||||
		devc->capture_ratio = g_variant_get_uint64(data);
 | 
							devc->capture_ratio = g_variant_get_uint64(data);
 | 
				
			||||||
		if (devc->capture_ratio > 100)
 | 
							break;
 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -246,43 +283,24 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	GVariant *gvar;
 | 
					 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
 | 
							*data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
 | 
				
			||||||
		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
 | 
					 | 
				
			||||||
			samplerates, ARRAY_SIZE(samplerates), sizeof(uint64_t));
 | 
					 | 
				
			||||||
		g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
 | 
					 | 
				
			||||||
		*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_TRIGGER_MATCH:
 | 
						case SR_CONF_TRIGGER_MATCH:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
 | 
							*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
 | 
				
			||||||
				soft_trigger_matches, ARRAY_SIZE(soft_trigger_matches),
 | 
					 | 
				
			||||||
				sizeof(int32_t));
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* get a sane timeout for poll() */
 | 
					/* get a sane timeout for poll() */
 | 
				
			||||||
| 
						 | 
					@ -292,25 +310,33 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
						GSList *l;
 | 
				
			||||||
	struct sr_trigger *trigger;
 | 
						struct sr_trigger *trigger;
 | 
				
			||||||
 | 
						struct sr_channel *channel;
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clear capture state */
 | 
						/* Clear capture state */
 | 
				
			||||||
	devc->bytes_read = 0;
 | 
						devc->bytes_read = 0;
 | 
				
			||||||
	devc->offset = 0;
 | 
						devc->offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Configure channels */
 | 
						/* Configure channels */
 | 
				
			||||||
	devc->sampleunit = g_slist_length(sdi->channels) > 8 ?
 | 
						devc->sampleunit = BL_SAMPLEUNIT_8_BITS;
 | 
				
			||||||
			BL_SAMPLEUNIT_16_BITS : BL_SAMPLEUNIT_8_BITS;
 | 
					
 | 
				
			||||||
	beaglelogic_set_sampleunit(devc);
 | 
						for (l = sdi->channels; l; l = l->next) {
 | 
				
			||||||
 | 
							channel = l->data;
 | 
				
			||||||
 | 
							if (channel->index >= 8 && channel->enabled)
 | 
				
			||||||
 | 
								devc->sampleunit = BL_SAMPLEUNIT_16_BITS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						devc->beaglelogic->set_sampleunit(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If continuous sampling, set the limit_samples to max possible value */
 | 
				
			||||||
 | 
						if (devc->triggerflags == BL_TRIGGERFLAGS_CONTINUOUS)
 | 
				
			||||||
 | 
							devc->limit_samples = UINT64_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Configure triggers & send header packet */
 | 
						/* Configure triggers & send header packet */
 | 
				
			||||||
	if ((trigger = sr_session_trigger_get(sdi->session))) {
 | 
						if ((trigger = sr_session_trigger_get(sdi->session))) {
 | 
				
			||||||
		int pre_trigger_samples = 0;
 | 
							int pre_trigger_samples = 0;
 | 
				
			||||||
		if (devc->limit_samples > 0)
 | 
							if (devc->limit_samples > 0)
 | 
				
			||||||
			pre_trigger_samples = devc->capture_ratio * devc->limit_samples/100;
 | 
								pre_trigger_samples = (devc->capture_ratio * devc->limit_samples) / 100;
 | 
				
			||||||
		devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples);
 | 
							devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples);
 | 
				
			||||||
		if (!devc->stl)
 | 
							if (!devc->stl)
 | 
				
			||||||
			return SR_ERR_MALLOC;
 | 
								return SR_ERR_MALLOC;
 | 
				
			||||||
| 
						 | 
					@ -320,9 +346,14 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Trigger and add poll on file */
 | 
						/* Trigger and add poll on file */
 | 
				
			||||||
	beaglelogic_start(devc);
 | 
						devc->beaglelogic->start(devc);
 | 
				
			||||||
 | 
						if (devc->beaglelogic == &beaglelogic_native_ops)
 | 
				
			||||||
		sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
 | 
							sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
 | 
				
			||||||
			BUFUNIT_TIMEOUT_MS(devc), beaglelogic_receive_data,
 | 
								BUFUNIT_TIMEOUT_MS(devc), beaglelogic_native_receive_data,
 | 
				
			||||||
 | 
								(void *)sdi);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							sr_session_source_add_pollfd(sdi->session, &devc->pollfd,
 | 
				
			||||||
 | 
								BUFUNIT_TIMEOUT_MS(devc), beaglelogic_tcp_receive_data,
 | 
				
			||||||
			(void *)sdi);
 | 
								(void *)sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
| 
						 | 
					@ -332,14 +363,14 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Execute a stop on BeagleLogic */
 | 
						/* Execute a stop on BeagleLogic */
 | 
				
			||||||
	beaglelogic_stop(devc);
 | 
						devc->beaglelogic->stop(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* lseek to offset 0, flushes the cache */
 | 
						/* Flush the cache */
 | 
				
			||||||
 | 
						if (devc->beaglelogic == &beaglelogic_native_ops)
 | 
				
			||||||
		lseek(devc->fd, 0, SEEK_SET);
 | 
							lseek(devc->fd, 0, SEEK_SET);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							beaglelogic_tcp_drain(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Remove session source and send EOT packet */
 | 
						/* Remove session source and send EOT packet */
 | 
				
			||||||
	sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
 | 
						sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
 | 
				
			||||||
| 
						 | 
					@ -356,6 +387,7 @@ static struct sr_dev_driver beaglelogic_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
 | 
						.dev_clear = dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2014 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
					 * Copyright (C) 2014-2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -47,12 +47,14 @@
 | 
				
			||||||
#define IOCTL_BL_GET_TRIGGER_FLAGS  _IOR('k', 0x23, uint32_t)
 | 
					#define IOCTL_BL_GET_TRIGGER_FLAGS  _IOR('k', 0x23, uint32_t)
 | 
				
			||||||
#define IOCTL_BL_SET_TRIGGER_FLAGS  _IOW('k', 0x23, uint32_t)
 | 
					#define IOCTL_BL_SET_TRIGGER_FLAGS  _IOW('k', 0x23, uint32_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IOCTL_BL_GET_CUR_INDEX      _IOR('k', 0x24, uint32_t)
 | 
				
			||||||
#define IOCTL_BL_CACHE_INVALIDATE    _IO('k', 0x25)
 | 
					#define IOCTL_BL_CACHE_INVALIDATE    _IO('k', 0x25)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IOCTL_BL_GET_BUFFER_SIZE    _IOR('k', 0x26, uint32_t)
 | 
					#define IOCTL_BL_GET_BUFFER_SIZE    _IOR('k', 0x26, uint32_t)
 | 
				
			||||||
#define IOCTL_BL_SET_BUFFER_SIZE    _IOW('k', 0x26, uint32_t)
 | 
					#define IOCTL_BL_SET_BUFFER_SIZE    _IOW('k', 0x26, uint32_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IOCTL_BL_GET_BUFUNIT_SIZE   _IOR('k', 0x27, uint32_t)
 | 
					#define IOCTL_BL_GET_BUFUNIT_SIZE   _IOR('k', 0x27, uint32_t)
 | 
				
			||||||
 | 
					#define IOCTL_BL_SET_BUFUNIT_SIZE   _IOW('k', 0x27, uint32_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IOCTL_BL_FILL_TEST_PATTERN   _IO('k', 0x28)
 | 
					#define IOCTL_BL_FILL_TEST_PATTERN   _IO('k', 0x28)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,120 +92,41 @@ enum beaglelogic_sampleunit {
 | 
				
			||||||
 * 	SR_OK or SR_ERR
 | 
					 * 	SR_OK or SR_ERR
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_open_nonblock(struct dev_context *devc);
 | 
					struct beaglelogic_ops {
 | 
				
			||||||
SR_PRIV int beaglelogic_close(struct dev_context *devc);
 | 
						int (*open)(struct dev_context *devc);
 | 
				
			||||||
 | 
						int (*close)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_get_buffersize(struct dev_context *devc);
 | 
						int (*get_buffersize)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_set_buffersize(struct dev_context *devc);
 | 
						int (*set_buffersize)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_get_samplerate(struct dev_context *devc);
 | 
						int (*get_samplerate)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_set_samplerate(struct dev_context *devc);
 | 
						int (*set_samplerate)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_get_sampleunit(struct dev_context *devc);
 | 
						int (*get_sampleunit)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_set_sampleunit(struct dev_context *devc);
 | 
						int (*set_sampleunit)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_get_triggerflags(struct dev_context *devc);
 | 
						int (*get_triggerflags)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_set_triggerflags(struct dev_context *devc);
 | 
						int (*set_triggerflags)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Start and stop the capture operation */
 | 
						/* Start and stop the capture operation */
 | 
				
			||||||
SR_PRIV int beaglelogic_start(struct dev_context *devc);
 | 
						int (*start)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_stop(struct dev_context *devc);
 | 
						int (*stop)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get the last error size */
 | 
						/* Get the last error size */
 | 
				
			||||||
SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc);
 | 
						int (*get_lasterror)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Gets the unit size of the capture buffer (usually 4 or 8 MB) */
 | 
						/* Gets the unit size of the capture buffer (usually 4 or 8 MB) */
 | 
				
			||||||
SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc);
 | 
						int (*get_bufunitsize)(struct dev_context *devc);
 | 
				
			||||||
 | 
						int (*set_bufunitsize)(struct dev_context *devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_mmap(struct dev_context *devc);
 | 
						int (*mmap)(struct dev_context *devc);
 | 
				
			||||||
SR_PRIV int beaglelogic_munmap(struct dev_context *devc);
 | 
						int (*munmap)(struct dev_context *devc);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Sources */
 | 
					SR_PRIV extern const struct beaglelogic_ops beaglelogic_native_ops;
 | 
				
			||||||
SR_PRIV inline int beaglelogic_open_nonblock(struct dev_context *devc) {
 | 
					SR_PRIV extern const struct beaglelogic_ops beaglelogic_tcp_ops;
 | 
				
			||||||
	devc->fd = open(BEAGLELOGIC_DEV_NODE, O_RDONLY | O_NONBLOCK);
 | 
					 | 
				
			||||||
	return (devc->fd == -1 ? SR_ERR : SR_OK);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV inline int beaglelogic_close(struct dev_context *devc) {
 | 
					SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc);
 | 
				
			||||||
	return close(devc->fd);
 | 
					SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_get_buffersize(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_GET_BUFFER_SIZE, &devc->buffersize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_set_buffersize(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_SET_BUFFER_SIZE, devc->buffersize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* This is treated differently as it gets a uint64_t while a uint32_t is read */
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_get_samplerate(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	uint32_t arg, err;
 | 
					 | 
				
			||||||
	err = ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_RATE, &arg);
 | 
					 | 
				
			||||||
	devc->cur_samplerate = arg;
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_set_samplerate(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_RATE,
 | 
					 | 
				
			||||||
			(uint32_t)devc->cur_samplerate);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_get_sampleunit(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_UNIT, &devc->sampleunit);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_set_sampleunit(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_UNIT, devc->sampleunit);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_get_triggerflags(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_GET_TRIGGER_FLAGS, &devc->triggerflags);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_set_triggerflags(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_SET_TRIGGER_FLAGS, devc->triggerflags);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int beaglelogic_getlasterror(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	int fd;
 | 
					 | 
				
			||||||
	char buf[16];
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((fd = open(BEAGLELOGIC_SYSFS_ATTR(lasterror), O_RDONLY)) == -1)
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ret = read(fd, buf, 16)) < 0)
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close(fd);
 | 
					 | 
				
			||||||
	devc->last_error = strtoul(buf, NULL, 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_start(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_START);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV inline int beaglelogic_stop(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_STOP);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int beaglelogic_get_bufunitsize(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return ioctl(devc->fd, IOCTL_BL_GET_BUFUNIT_SIZE, &devc->bufunitsize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int beaglelogic_mmap(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	if (!devc->buffersize)
 | 
					 | 
				
			||||||
		beaglelogic_get_buffersize(devc);
 | 
					 | 
				
			||||||
	devc->sample_buf = mmap(NULL, devc->buffersize,
 | 
					 | 
				
			||||||
			PROT_READ, MAP_SHARED, devc->fd, 0);
 | 
					 | 
				
			||||||
	return (devc->sample_buf == MAP_FAILED ? -1 : SR_OK);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int beaglelogic_munmap(struct dev_context *devc) {
 | 
					 | 
				
			||||||
	return munmap(devc->sample_buf, devc->buffersize);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,155 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2014-2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					#include "beaglelogic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_open_nonblock(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						devc->fd = open(BEAGLELOGIC_DEV_NODE, O_RDONLY | O_NONBLOCK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ((devc->fd == -1) ? SR_ERR : SR_OK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_close(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return close(devc->fd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_buffersize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_GET_BUFFER_SIZE, &devc->buffersize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_buffersize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_SET_BUFFER_SIZE, devc->buffersize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This is treated differently as it gets a uint64_t while a uint32_t is read */
 | 
				
			||||||
 | 
					static int beaglelogic_get_samplerate(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint32_t arg, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_RATE, &arg);
 | 
				
			||||||
 | 
						devc->cur_samplerate = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_samplerate(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_RATE,
 | 
				
			||||||
 | 
								(uint32_t)devc->cur_samplerate);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_sampleunit(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_GET_SAMPLE_UNIT, &devc->sampleunit);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_sampleunit(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_SET_SAMPLE_UNIT, devc->sampleunit);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_triggerflags(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_GET_TRIGGER_FLAGS, &devc->triggerflags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_triggerflags(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_SET_TRIGGER_FLAGS, devc->triggerflags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_lasterror(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
						char buf[16];
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((fd = open(BEAGLELOGIC_SYSFS_ATTR(lasterror), O_RDONLY)) == -1)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = read(fd, buf, 16);
 | 
				
			||||||
 | 
						close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc->last_error = strtoul(buf, NULL, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_start(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_START);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_stop(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_STOP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_bufunitsize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_GET_BUFUNIT_SIZE, &devc->bufunitsize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_bufunitsize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ioctl(devc->fd, IOCTL_BL_SET_BUFUNIT_SIZE, devc->bufunitsize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_mmap(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!devc->buffersize)
 | 
				
			||||||
 | 
							beaglelogic_get_buffersize(devc);
 | 
				
			||||||
 | 
						devc->sample_buf = mmap(NULL, devc->buffersize,
 | 
				
			||||||
 | 
								PROT_READ, MAP_SHARED, devc->fd, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ((devc->sample_buf == MAP_FAILED) ? -1 : SR_OK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_munmap(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return munmap(devc->sample_buf, devc->buffersize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const struct beaglelogic_ops beaglelogic_native_ops = {
 | 
				
			||||||
 | 
						.open = beaglelogic_open_nonblock,
 | 
				
			||||||
 | 
						.close = beaglelogic_close,
 | 
				
			||||||
 | 
						.get_buffersize = beaglelogic_get_buffersize,
 | 
				
			||||||
 | 
						.set_buffersize = beaglelogic_set_buffersize,
 | 
				
			||||||
 | 
						.get_samplerate = beaglelogic_get_samplerate,
 | 
				
			||||||
 | 
						.set_samplerate = beaglelogic_set_samplerate,
 | 
				
			||||||
 | 
						.get_sampleunit = beaglelogic_get_sampleunit,
 | 
				
			||||||
 | 
						.set_sampleunit = beaglelogic_set_sampleunit,
 | 
				
			||||||
 | 
						.get_triggerflags = beaglelogic_get_triggerflags,
 | 
				
			||||||
 | 
						.set_triggerflags = beaglelogic_set_triggerflags,
 | 
				
			||||||
 | 
						.start = beaglelogic_start,
 | 
				
			||||||
 | 
						.stop = beaglelogic_stop,
 | 
				
			||||||
 | 
						.get_lasterror = beaglelogic_get_lasterror,
 | 
				
			||||||
 | 
						.get_bufunitsize = beaglelogic_get_bufunitsize,
 | 
				
			||||||
 | 
						.set_bufunitsize = beaglelogic_set_bufunitsize,
 | 
				
			||||||
 | 
						.mmap = beaglelogic_mmap,
 | 
				
			||||||
 | 
						.munmap = beaglelogic_munmap,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,430 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 | 
					 * Portions of the code are adapted from scpi_tcp.c and scpi.c, their
 | 
				
			||||||
 | 
					 * copyright notices are listed below:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
 | 
				
			||||||
 | 
					 * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					#define _WIN32_WINNT 0x0501
 | 
				
			||||||
 | 
					#include <winsock2.h>
 | 
				
			||||||
 | 
					#include <ws2tcpip.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include <glib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#ifndef _WIN32
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <netinet/in.h>
 | 
				
			||||||
 | 
					#include <arpa/inet.h>
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					#include "beaglelogic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_tcp_open(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct addrinfo hints;
 | 
				
			||||||
 | 
						struct addrinfo *results, *res;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&hints, 0, sizeof(hints));
 | 
				
			||||||
 | 
						hints.ai_family = AF_UNSPEC;
 | 
				
			||||||
 | 
						hints.ai_socktype = SOCK_STREAM;
 | 
				
			||||||
 | 
						hints.ai_protocol = IPPROTO_TCP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = getaddrinfo(devc->address, devc->port, &hints, &results);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (err) {
 | 
				
			||||||
 | 
							sr_err("Address lookup failed: %s:%s: %s", devc->address,
 | 
				
			||||||
 | 
								devc->port, gai_strerror(err));
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (res = results; res; res = res->ai_next) {
 | 
				
			||||||
 | 
							if ((devc->socket = socket(res->ai_family, res->ai_socktype,
 | 
				
			||||||
 | 
											res->ai_protocol)) < 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (connect(devc->socket, res->ai_addr, res->ai_addrlen) != 0) {
 | 
				
			||||||
 | 
								close(devc->socket);
 | 
				
			||||||
 | 
								devc->socket = -1;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						freeaddrinfo(results);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (devc->socket < 0) {
 | 
				
			||||||
 | 
							sr_err("Failed to connect to %s:%s: %s", devc->address,
 | 
				
			||||||
 | 
								devc->port, g_strerror(errno));
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
 | 
				
			||||||
 | 
									    const char *format, ...)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len, out;
 | 
				
			||||||
 | 
						va_list args, args_copy;
 | 
				
			||||||
 | 
						char *buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						va_start(args, format);
 | 
				
			||||||
 | 
						va_copy(args_copy, args);
 | 
				
			||||||
 | 
						len = vsnprintf(NULL, 0, format, args_copy);
 | 
				
			||||||
 | 
						va_end(args_copy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = g_malloc0(len + 2);
 | 
				
			||||||
 | 
						vsprintf(buf, format, args);
 | 
				
			||||||
 | 
						va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (buf[len - 1] != '\n')
 | 
				
			||||||
 | 
							buf[len] = '\n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out = send(devc->socket, buf, strlen(buf), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (out < 0) {
 | 
				
			||||||
 | 
							sr_err("Send error: %s", g_strerror(errno));
 | 
				
			||||||
 | 
							g_free(buf);
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (out < (int)strlen(buf)) {
 | 
				
			||||||
 | 
							sr_dbg("Only sent %d/%zu bytes of command: '%s'.", out,
 | 
				
			||||||
 | 
							       strlen(buf), buf);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("Sent command: '%s'.", buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
 | 
				
			||||||
 | 
									     int maxlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						len = recv(devc->socket, buf, maxlen, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len < 0) {
 | 
				
			||||||
 | 
							sr_err("Receive error: %s", g_strerror(errno));
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *buf = g_malloc(1024);
 | 
				
			||||||
 | 
						fd_set rset;
 | 
				
			||||||
 | 
						int ret, len = 0;
 | 
				
			||||||
 | 
						struct timeval tv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						FD_ZERO(&rset);
 | 
				
			||||||
 | 
						FD_SET(devc->socket, &rset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* 25ms timeout */
 | 
				
			||||||
 | 
						tv.tv_sec = 0;
 | 
				
			||||||
 | 
						tv.tv_usec = 25 * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							ret = select(devc->socket + 1, &rset, NULL, NULL, &tv);
 | 
				
			||||||
 | 
							if (ret > 0)
 | 
				
			||||||
 | 
								len += beaglelogic_tcp_read_data(devc, buf, 1024);
 | 
				
			||||||
 | 
						} while (ret > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("Drained %d bytes of data.", len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
 | 
				
			||||||
 | 
									      char **tcp_resp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						GString *response = g_string_sized_new(1024);
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
						gint64 timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*tcp_resp = NULL;
 | 
				
			||||||
 | 
						if (cmd) {
 | 
				
			||||||
 | 
							if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK)
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timeout = g_get_monotonic_time() + devc->read_timeout;
 | 
				
			||||||
 | 
						len = beaglelogic_tcp_read_data(devc, response->str,
 | 
				
			||||||
 | 
										response->allocated_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len < 0) {
 | 
				
			||||||
 | 
							g_string_free(response, TRUE);
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (len > 0)
 | 
				
			||||||
 | 
							g_string_set_size(response, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (g_get_monotonic_time() > timeout) {
 | 
				
			||||||
 | 
							sr_err("Timed out waiting for response.");
 | 
				
			||||||
 | 
							g_string_free(response, TRUE);
 | 
				
			||||||
 | 
							return SR_ERR_TIMEOUT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Remove trailing newline if present */
 | 
				
			||||||
 | 
						if (response->len >= 1 && response->str[response->len - 1] == '\n')
 | 
				
			||||||
 | 
							g_string_truncate(response, response->len - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Remove trailing carriage return if present */
 | 
				
			||||||
 | 
						if (response->len >= 1 && response->str[response->len - 1] == '\r')
 | 
				
			||||||
 | 
							g_string_truncate(response, response->len - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
 | 
				
			||||||
 | 
							response->str, response->len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*tcp_resp = g_string_free(response, FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_tcp_get_int(struct dev_context *devc,
 | 
				
			||||||
 | 
									   const char *cmd, int *response)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
 | 
				
			||||||
 | 
						if (!resp && ret != SR_OK)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sr_atoi(resp, response) == SR_OK)
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR_DATA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *resp = NULL;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, "version", &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_open(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_open(devc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_close(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (close(devc->socket) < 0)
 | 
				
			||||||
 | 
							return SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_buffersize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_get_int(devc, "memalloc",
 | 
				
			||||||
 | 
							(int *)&devc->buffersize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_buffersize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beaglelogic_tcp_send_cmd(devc, "memalloc %" PRIu32, devc->buffersize);
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_samplerate(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int arg, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						devc->cur_samplerate = arg;
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_samplerate(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beaglelogic_tcp_send_cmd(devc, "samplerate %" PRIu32,
 | 
				
			||||||
 | 
							(uint32_t)devc->cur_samplerate);
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_sampleunit(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_get_int(devc, "sampleunit",
 | 
				
			||||||
 | 
							(int *)&devc->sampleunit);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_sampleunit(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beaglelogic_tcp_send_cmd(devc, "sampleunit %" PRIu32, devc->sampleunit);
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_triggerflags(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_get_int(devc, "triggerflags",
 | 
				
			||||||
 | 
							(int *)&devc->triggerflags);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_triggerflags(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beaglelogic_tcp_send_cmd(devc, "triggerflags %" PRIu32, devc->triggerflags);
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_lasterror(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						devc->last_error = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_start(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						beaglelogic_tcp_drain(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return beaglelogic_tcp_send_cmd(devc, "get");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_stop(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_send_cmd(devc, "close");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_get_bufunitsize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return beaglelogic_tcp_get_int(devc, "bufunitsize",
 | 
				
			||||||
 | 
							(int *)&devc->bufunitsize);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int beaglelogic_set_bufunitsize(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						char *resp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beaglelogic_tcp_send_cmd(devc, "bufunitsize %" PRIu32, devc->bufunitsize);
 | 
				
			||||||
 | 
						ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
 | 
				
			||||||
 | 
						if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
 | 
				
			||||||
 | 
							ret = SR_OK;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = SR_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g_free(resp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dummy(struct dev_context *devc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						(void)devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SR_ERR_NA;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
 | 
				
			||||||
 | 
						.open = beaglelogic_open,
 | 
				
			||||||
 | 
						.close = beaglelogic_close,
 | 
				
			||||||
 | 
						.get_buffersize = beaglelogic_get_buffersize,
 | 
				
			||||||
 | 
						.set_buffersize = beaglelogic_set_buffersize,
 | 
				
			||||||
 | 
						.get_samplerate = beaglelogic_get_samplerate,
 | 
				
			||||||
 | 
						.set_samplerate = beaglelogic_set_samplerate,
 | 
				
			||||||
 | 
						.get_sampleunit = beaglelogic_get_sampleunit,
 | 
				
			||||||
 | 
						.set_sampleunit = beaglelogic_set_sampleunit,
 | 
				
			||||||
 | 
						.get_triggerflags = beaglelogic_get_triggerflags,
 | 
				
			||||||
 | 
						.set_triggerflags = beaglelogic_set_triggerflags,
 | 
				
			||||||
 | 
						.start = beaglelogic_start,
 | 
				
			||||||
 | 
						.stop = beaglelogic_stop,
 | 
				
			||||||
 | 
						.get_lasterror = beaglelogic_get_lasterror,
 | 
				
			||||||
 | 
						.get_bufunitsize = beaglelogic_get_bufunitsize,
 | 
				
			||||||
 | 
						.set_bufunitsize = beaglelogic_set_bufunitsize,
 | 
				
			||||||
 | 
						.mmap = dummy,
 | 
				
			||||||
 | 
						.munmap = dummy,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2014 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
					 * Copyright (C) 2014-2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,16 @@
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					#define _WIN32_WINNT 0x0501
 | 
				
			||||||
 | 
					#include <winsock2.h>
 | 
				
			||||||
 | 
					#include <ws2tcpip.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					#include "beaglelogic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Define data packet size independent of packet (bufunitsize bytes) size
 | 
					/* Define data packet size independent of packet (bufunitsize bytes) size
 | 
				
			||||||
 * from the BeagleLogic kernel module */
 | 
					 * from the BeagleLogic kernel module */
 | 
				
			||||||
| 
						 | 
					@ -32,7 +41,7 @@
 | 
				
			||||||
 * kernel buffers appropriately. It is up to the application which is
 | 
					 * kernel buffers appropriately. It is up to the application which is
 | 
				
			||||||
 * using libsigrok to decide how to deal with the data.
 | 
					 * using libsigrok to decide how to deal with the data.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 | 
					SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct sr_dev_inst *sdi;
 | 
						const struct sr_dev_inst *sdi;
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
| 
						 | 
					@ -90,7 +99,7 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
		if ((devc->offset += packetsize) >= devc->buffersize) {
 | 
							if ((devc->offset += packetsize) >= devc->buffersize) {
 | 
				
			||||||
			/* One shot capture, we abort and settle with less than
 | 
								/* One shot capture, we abort and settle with less than
 | 
				
			||||||
			 * the required number of samples */
 | 
								 * the required number of samples */
 | 
				
			||||||
			if (devc->triggerflags)
 | 
								if (devc->triggerflags == BL_TRIGGERFLAGS_CONTINUOUS)
 | 
				
			||||||
				devc->offset = 0;
 | 
									devc->offset = 0;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				packetsize = 0;
 | 
									packetsize = 0;
 | 
				
			||||||
| 
						 | 
					@ -107,3 +116,90 @@ SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SR_PRIV int beaglelogic_tcp_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct sr_dev_inst *sdi;
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
						struct sr_datafeed_packet packet;
 | 
				
			||||||
 | 
						struct sr_datafeed_logic logic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
						int pre_trigger_samples;
 | 
				
			||||||
 | 
						int trigger_offset;
 | 
				
			||||||
 | 
						uint32_t packetsize;
 | 
				
			||||||
 | 
						uint64_t bytes_remaining;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(sdi = cb_data) || !(devc = sdi->priv))
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packetsize = TCP_BUFFER_SIZE;
 | 
				
			||||||
 | 
						logic.unitsize = SAMPLEUNIT_TO_BYTES(devc->sampleunit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (revents == G_IO_IN) {
 | 
				
			||||||
 | 
							sr_info("In callback G_IO_IN");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							len = recv(fd, devc->tcp_buffer, TCP_BUFFER_SIZE, 0);
 | 
				
			||||||
 | 
							if (len < 0) {
 | 
				
			||||||
 | 
								sr_err("Receive error: %s", g_strerror(errno));
 | 
				
			||||||
 | 
								return SR_ERR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							packetsize = len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bytes_remaining = (devc->limit_samples * logic.unitsize) -
 | 
				
			||||||
 | 
									devc->bytes_read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Configure data packet */
 | 
				
			||||||
 | 
							packet.type = SR_DF_LOGIC;
 | 
				
			||||||
 | 
							packet.payload = &logic;
 | 
				
			||||||
 | 
							logic.data = devc->tcp_buffer;
 | 
				
			||||||
 | 
							logic.length = MIN(packetsize, bytes_remaining);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (devc->trigger_fired) {
 | 
				
			||||||
 | 
								/* Send the incoming transfer to the session bus. */
 | 
				
			||||||
 | 
								sr_session_send(sdi, &packet);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Check for trigger */
 | 
				
			||||||
 | 
								trigger_offset = soft_trigger_logic_check(devc->stl,
 | 
				
			||||||
 | 
										logic.data, packetsize, &pre_trigger_samples);
 | 
				
			||||||
 | 
								if (trigger_offset > -1) {
 | 
				
			||||||
 | 
									devc->bytes_read += pre_trigger_samples * logic.unitsize;
 | 
				
			||||||
 | 
									trigger_offset *= logic.unitsize;
 | 
				
			||||||
 | 
									logic.length = MIN(packetsize - trigger_offset,
 | 
				
			||||||
 | 
											bytes_remaining);
 | 
				
			||||||
 | 
									logic.data += trigger_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									sr_session_send(sdi, &packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									devc->trigger_fired = TRUE;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Update byte count and offset (roll over if needed) */
 | 
				
			||||||
 | 
							devc->bytes_read += logic.length;
 | 
				
			||||||
 | 
							if ((devc->offset += packetsize) >= devc->buffersize) {
 | 
				
			||||||
 | 
								/* One shot capture, we abort and settle with less than
 | 
				
			||||||
 | 
								 * the required number of samples */
 | 
				
			||||||
 | 
								if (devc->triggerflags == BL_TRIGGERFLAGS_CONTINUOUS)
 | 
				
			||||||
 | 
									devc->offset = 0;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									packetsize = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* EOF Received or we have reached the limit */
 | 
				
			||||||
 | 
						if (devc->bytes_read >= devc->limit_samples * logic.unitsize ||
 | 
				
			||||||
 | 
								packetsize == 0) {
 | 
				
			||||||
 | 
							/* Send EOA Packet, stop polling */
 | 
				
			||||||
 | 
							std_session_send_df_end(sdi);
 | 
				
			||||||
 | 
							devc->beaglelogic->stop(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Drain the receive buffer */
 | 
				
			||||||
 | 
							beaglelogic_tcp_drain(devc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sr_session_source_remove_pollfd(sdi->session, &devc->pollfd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 * This file is part of the libsigrok project.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (C) 2014 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
					 * Copyright (C) 2014-2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 * This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -32,12 +32,23 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SAMPLEUNIT_TO_BYTES(x)	((x) == 1 ? 1 : 2)
 | 
					#define SAMPLEUNIT_TO_BYTES(x)	((x) == 1 ? 1 : 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TCP_BUFFER_SIZE         (128 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					/** Private, per-device-instance driver context. */
 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	/* Model-specific information */
 | 
					 | 
				
			||||||
	int max_channels;
 | 
						int max_channels;
 | 
				
			||||||
	uint32_t fw_ver;
 | 
						uint32_t fw_ver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Operations */
 | 
				
			||||||
 | 
						const struct beaglelogic_ops *beaglelogic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* TCP Settings */
 | 
				
			||||||
 | 
						char *address;
 | 
				
			||||||
 | 
						char *port;
 | 
				
			||||||
 | 
						int socket;
 | 
				
			||||||
 | 
						unsigned int read_timeout;
 | 
				
			||||||
 | 
						unsigned char *tcp_buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Acquisition settings: see beaglelogic.h */
 | 
						/* Acquisition settings: see beaglelogic.h */
 | 
				
			||||||
	uint64_t cur_samplerate;
 | 
						uint64_t cur_samplerate;
 | 
				
			||||||
	uint64_t limit_samples;
 | 
						uint64_t limit_samples;
 | 
				
			||||||
| 
						 | 
					@ -49,7 +60,6 @@ struct dev_context {
 | 
				
			||||||
	uint32_t bufunitsize;
 | 
						uint32_t bufunitsize;
 | 
				
			||||||
	uint32_t buffersize;
 | 
						uint32_t buffersize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Operational state */
 | 
					 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	GPollFD pollfd;
 | 
						GPollFD pollfd;
 | 
				
			||||||
	int last_error;
 | 
						int last_error;
 | 
				
			||||||
| 
						 | 
					@ -64,6 +74,7 @@ struct dev_context {
 | 
				
			||||||
	gboolean trigger_fired;
 | 
						gboolean trigger_fired;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int beaglelogic_receive_data(int fd, int revents, void *cb_data);
 | 
					SR_PRIV int beaglelogic_native_receive_data(int fd, int revents, void *cb_data);
 | 
				
			||||||
 | 
					SR_PRIV int beaglelogic_tcp_receive_data(int fd, int revents, void *cb_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,258 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
#include "protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define BRYMEN_BC86X "0820.0001"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint32_t scanopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_CONN,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_MULTIMETER,
 | 
					 | 
				
			||||||
	SR_CONF_CONTINUOUS,
 | 
					 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 | 
					 | 
				
			||||||
	SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	GSList *usb_devices, *devices, *l;
 | 
					 | 
				
			||||||
	struct drv_context *drvc;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
					 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
					 | 
				
			||||||
	struct sr_config *src;
 | 
					 | 
				
			||||||
	const char *conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	drvc = di->context;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conn = BRYMEN_BC86X;
 | 
					 | 
				
			||||||
	for (l = options; l; l = l->next) {
 | 
					 | 
				
			||||||
		src = l->data;
 | 
					 | 
				
			||||||
		switch (src->key) {
 | 
					 | 
				
			||||||
		case SR_CONF_CONN:
 | 
					 | 
				
			||||||
			conn = g_variant_get_string(src->data, NULL);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devices = NULL;
 | 
					 | 
				
			||||||
	if (!(usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn))) {
 | 
					 | 
				
			||||||
		g_slist_free_full(usb_devices, g_free);
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (l = usb_devices; l; l = l->next) {
 | 
					 | 
				
			||||||
		usb = l->data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
					 | 
				
			||||||
		sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
		sdi->vendor = g_strdup("Brymen");
 | 
					 | 
				
			||||||
		sdi->model = g_strdup("BM869");
 | 
					 | 
				
			||||||
		devc = g_malloc0(sizeof(struct dev_context));
 | 
					 | 
				
			||||||
		sdi->priv = devc;
 | 
					 | 
				
			||||||
		sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1");
 | 
					 | 
				
			||||||
		sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P2");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sdi->inst_type = SR_INST_USB;
 | 
					 | 
				
			||||||
		sdi->conn = usb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sr_sw_limits_init(&devc->sw_limits);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		devices = g_slist_append(devices, sdi);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return std_scan_complete(di, devices);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_open(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_dev_driver *di = sdi->driver;
 | 
					 | 
				
			||||||
	struct drv_context *drvc = di->context;
 | 
					 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb = sdi->conn;
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb)) == SR_OK)
 | 
					 | 
				
			||||||
		sdi->status = SR_ST_ACTIVE;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Detach kernel drivers which grabbed this device (if any). */
 | 
					 | 
				
			||||||
	if (libusb_kernel_driver_active(usb->devhdl, 0) == 1) {
 | 
					 | 
				
			||||||
		ret = libusb_detach_kernel_driver(usb->devhdl, 0);
 | 
					 | 
				
			||||||
		if (ret < 0) {
 | 
					 | 
				
			||||||
			sr_err("Failed to detach kernel driver: %s.",
 | 
					 | 
				
			||||||
			       libusb_error_name(ret));
 | 
					 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		devc->detached_kernel_driver = 1;
 | 
					 | 
				
			||||||
		sr_dbg("Successfully detached kernel driver.");
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		sr_dbg("No need to detach a kernel driver.");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Claim interface 0. */
 | 
					 | 
				
			||||||
	if ((ret = libusb_claim_interface(usb->devhdl, 0)) < 0) {
 | 
					 | 
				
			||||||
		sr_err("Failed to claim interface 0: %s.",
 | 
					 | 
				
			||||||
		       libusb_error_name(ret));
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sr_dbg("Successfully claimed interface 0.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_close(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb = sdi->conn;
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ret = libusb_release_interface(usb->devhdl, 0)))
 | 
					 | 
				
			||||||
		sr_err("Failed to release interface 0: %s.\n", libusb_error_name(ret));
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		sr_dbg("Successfully released interface 0.\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!ret && devc->detached_kernel_driver) {
 | 
					 | 
				
			||||||
		if ((ret = libusb_attach_kernel_driver(usb->devhdl, 0))) {
 | 
					 | 
				
			||||||
			sr_err("Failed to attach kernel driver: %s.\n",
 | 
					 | 
				
			||||||
			       libusb_error_name(ret));
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			devc->detached_kernel_driver = 0;
 | 
					 | 
				
			||||||
			sr_dbg("Successfully attached kernel driver.\n");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	libusb_close(usb->devhdl);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sr_sw_limits_config_get(&devc->sw_limits, key, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sr_sw_limits_config_set(&devc->sw_limits, key, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->sw_limits);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_session_source_add(sdi->session, -1, 0, 10,
 | 
					 | 
				
			||||||
			brymen_bm86x_receive_data, (void *)sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	std_session_send_df_end(sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_session_source_remove(sdi->session, -1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct sr_dev_driver brymen_bm86x_driver_info = {
 | 
					 | 
				
			||||||
	.name = "brymen-bm86x",
 | 
					 | 
				
			||||||
	.longname = "Brymen BM86X",
 | 
					 | 
				
			||||||
	.api_version = 1,
 | 
					 | 
				
			||||||
	.init = std_init,
 | 
					 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
					 | 
				
			||||||
	.scan = scan,
 | 
					 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
					 | 
				
			||||||
	.dev_clear = NULL,
 | 
					 | 
				
			||||||
	.config_get = config_get,
 | 
					 | 
				
			||||||
	.config_set = config_set,
 | 
					 | 
				
			||||||
	.config_list = config_list,
 | 
					 | 
				
			||||||
	.dev_open = dev_open,
 | 
					 | 
				
			||||||
	.dev_close = dev_close,
 | 
					 | 
				
			||||||
	.dev_acquisition_start = dev_acquisition_start,
 | 
					 | 
				
			||||||
	.dev_acquisition_stop = dev_acquisition_stop,
 | 
					 | 
				
			||||||
	.context = NULL,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
SR_REGISTER_DEV_DRIVER(brymen_bm86x_driver_info);
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,350 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2014 Aurelien Jacobs <aurel@gnuage.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <math.h>
 | 
					 | 
				
			||||||
#include "protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_TIMEOUT 500
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char char_map[128] = {
 | 
					 | 
				
			||||||
	[0x20] = '-',
 | 
					 | 
				
			||||||
	[0x5F] = '0',
 | 
					 | 
				
			||||||
	[0x50] = '1',
 | 
					 | 
				
			||||||
	[0x6D] = '2',
 | 
					 | 
				
			||||||
	[0x7C] = '3',
 | 
					 | 
				
			||||||
	[0x72] = '4',
 | 
					 | 
				
			||||||
	[0x3E] = '5',
 | 
					 | 
				
			||||||
	[0x3F] = '6',
 | 
					 | 
				
			||||||
	[0x54] = '7',
 | 
					 | 
				
			||||||
	[0x7F] = '8',
 | 
					 | 
				
			||||||
	[0x7E] = '9',
 | 
					 | 
				
			||||||
	[0x0F] = 'C',
 | 
					 | 
				
			||||||
	[0x27] = 'F',
 | 
					 | 
				
			||||||
	[0x0B] = 'L',
 | 
					 | 
				
			||||||
	[0x79] = 'd',
 | 
					 | 
				
			||||||
	[0x10] = 'i',
 | 
					 | 
				
			||||||
	[0x39] = 'o',
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int brymen_bm86x_parse_digits(const unsigned char *buf, int length,
 | 
					 | 
				
			||||||
                                     char *str, float *floatval,
 | 
					 | 
				
			||||||
                                     char *temp_unit, int *digits, int flag)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char c, *p = str;
 | 
					 | 
				
			||||||
	int i, ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*digits = INT_MIN;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buf[0] & flag)
 | 
					 | 
				
			||||||
		*p++ = '-';
 | 
					 | 
				
			||||||
	for (i = 0; i < length; i++) {
 | 
					 | 
				
			||||||
		if (i && i < 5 && buf[i+1] & 0x01) {
 | 
					 | 
				
			||||||
			*p++ = '.';
 | 
					 | 
				
			||||||
			*digits = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c = char_map[buf[i+1] >> 1];
 | 
					 | 
				
			||||||
		if (i == 5 && (c == 'C' || c == 'F'))
 | 
					 | 
				
			||||||
			*temp_unit = c;
 | 
					 | 
				
			||||||
		else if (c) {
 | 
					 | 
				
			||||||
			*p++ = c;
 | 
					 | 
				
			||||||
			(*digits)++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*p = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (*digits < 0)
 | 
					 | 
				
			||||||
		*digits = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((ret = sr_atof_ascii(str, floatval))) {
 | 
					 | 
				
			||||||
		sr_dbg("invalid float string: '%s'", str);
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void brymen_bm86x_parse(unsigned char *buf, float *floatval,
 | 
					 | 
				
			||||||
                               struct sr_datafeed_analog *analog)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char str[16], temp_unit;
 | 
					 | 
				
			||||||
	int ret1, ret2, digits[2], over_limit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret1 = brymen_bm86x_parse_digits(buf+2, 6, str, &floatval[0],
 | 
					 | 
				
			||||||
	                                 &temp_unit, &digits[0], 0x80);
 | 
					 | 
				
			||||||
	over_limit = strstr(str, "0L") || strstr(str, "0.L");
 | 
					 | 
				
			||||||
	ret2 = brymen_bm86x_parse_digits(buf+9, 4, str, &floatval[1],
 | 
					 | 
				
			||||||
	                                 &temp_unit, &digits[1], 0x10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* main display */
 | 
					 | 
				
			||||||
	if (ret1 == SR_OK || over_limit) {
 | 
					 | 
				
			||||||
		/* SI unit */
 | 
					 | 
				
			||||||
		if (buf[8] & 0x01) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_VOLTAGE;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_VOLT;
 | 
					 | 
				
			||||||
			if (!strcmp(str, "diod"))
 | 
					 | 
				
			||||||
				analog[0].meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
					 | 
				
			||||||
		} else if (buf[14] & 0x80) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_CURRENT;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_AMPERE;
 | 
					 | 
				
			||||||
		} else if (buf[14] & 0x20) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_CAPACITANCE;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_FARAD;
 | 
					 | 
				
			||||||
		} else if (buf[14] & 0x10) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_CONDUCTANCE;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_SIEMENS;
 | 
					 | 
				
			||||||
		} else if (buf[15] & 0x01) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_FREQUENCY;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_HERTZ;
 | 
					 | 
				
			||||||
		} else if (buf[10] & 0x01) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_CONTINUITY;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_OHM;
 | 
					 | 
				
			||||||
		} else if (buf[15] & 0x10) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_RESISTANCE;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_OHM;
 | 
					 | 
				
			||||||
		} else if (buf[15] & 0x02) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_POWER;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
					 | 
				
			||||||
		} else if (buf[15] & 0x80) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
					 | 
				
			||||||
			analog[0].meaning->unit = SR_UNIT_PERCENTAGE;
 | 
					 | 
				
			||||||
		} else if (buf[ 2] & 0x0A) {
 | 
					 | 
				
			||||||
			analog[0].meaning->mq = SR_MQ_TEMPERATURE;
 | 
					 | 
				
			||||||
			if (temp_unit == 'F')
 | 
					 | 
				
			||||||
				analog[0].meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				analog[0].meaning->unit = SR_UNIT_CELSIUS;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* when MIN MAX and AVG are displayed at the same time, remove them */
 | 
					 | 
				
			||||||
		if ((buf[1] & 0xE0) == 0xE0)
 | 
					 | 
				
			||||||
			buf[1] &= ~0xE0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* AC/DC/Auto flags */
 | 
					 | 
				
			||||||
		if (buf[1] & 0x10)  analog[0].meaning->mqflags |= SR_MQFLAG_DC;
 | 
					 | 
				
			||||||
		if (buf[2] & 0x01)  analog[0].meaning->mqflags |= SR_MQFLAG_AC;
 | 
					 | 
				
			||||||
		if (buf[1] & 0x01)  analog[0].meaning->mqflags |= SR_MQFLAG_AUTORANGE;
 | 
					 | 
				
			||||||
		if (buf[1] & 0x08)  analog[0].meaning->mqflags |= SR_MQFLAG_HOLD;
 | 
					 | 
				
			||||||
		if (buf[1] & 0x20)  analog[0].meaning->mqflags |= SR_MQFLAG_MAX;
 | 
					 | 
				
			||||||
		if (buf[1] & 0x40)  analog[0].meaning->mqflags |= SR_MQFLAG_MIN;
 | 
					 | 
				
			||||||
		if (buf[1] & 0x80)  analog[0].meaning->mqflags |= SR_MQFLAG_AVG;
 | 
					 | 
				
			||||||
		if (buf[3] & 0x01)  analog[0].meaning->mqflags |= SR_MQFLAG_RELATIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* when dBm is displayed, remove the m suffix so that it is
 | 
					 | 
				
			||||||
		   not considered as the 10e-3 SI prefix */
 | 
					 | 
				
			||||||
		if (buf[15] & 0x02)
 | 
					 | 
				
			||||||
			buf[15] &= ~0x04;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* SI prefix */
 | 
					 | 
				
			||||||
		if (buf[14] & 0x40)  { floatval[0] *= 1e-9; digits[0] += 9; } /* n */
 | 
					 | 
				
			||||||
		if (buf[15] & 0x08)  { floatval[0] *= 1e-6; digits[0] += 6; } /* µ */
 | 
					 | 
				
			||||||
		if (buf[15] & 0x04)  { floatval[0] *= 1e-3; digits[0] += 3; } /* m */
 | 
					 | 
				
			||||||
		if (buf[15] & 0x40)  { floatval[0] *= 1e3;  digits[0] -= 3; } /* k */
 | 
					 | 
				
			||||||
		if (buf[15] & 0x20)  { floatval[0] *= 1e6;  digits[0] -= 6; } /* M */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (over_limit)      floatval[0] = INFINITY;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		analog[0].encoding->digits  = digits[0];
 | 
					 | 
				
			||||||
		analog[0].spec->spec_digits = digits[0];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* secondary display */
 | 
					 | 
				
			||||||
	if (ret2 == SR_OK) {
 | 
					 | 
				
			||||||
		/* SI unit */
 | 
					 | 
				
			||||||
		if (buf[14] & 0x08) {
 | 
					 | 
				
			||||||
			analog[1].meaning->mq = SR_MQ_VOLTAGE;
 | 
					 | 
				
			||||||
			analog[1].meaning->unit = SR_UNIT_VOLT;
 | 
					 | 
				
			||||||
		} else if (buf[9] & 0x04) {
 | 
					 | 
				
			||||||
			analog[1].meaning->mq = SR_MQ_CURRENT;
 | 
					 | 
				
			||||||
			analog[1].meaning->unit = SR_UNIT_AMPERE;
 | 
					 | 
				
			||||||
		} else if (buf[9] & 0x08) {
 | 
					 | 
				
			||||||
			analog[1].meaning->mq = SR_MQ_CURRENT;
 | 
					 | 
				
			||||||
			analog[1].meaning->unit = SR_UNIT_PERCENTAGE;
 | 
					 | 
				
			||||||
		} else if (buf[14] & 0x04) {
 | 
					 | 
				
			||||||
			analog[1].meaning->mq = SR_MQ_FREQUENCY;
 | 
					 | 
				
			||||||
			analog[1].meaning->unit = SR_UNIT_HERTZ;
 | 
					 | 
				
			||||||
		} else if (buf[9] & 0x40) {
 | 
					 | 
				
			||||||
			analog[1].meaning->mq = SR_MQ_TEMPERATURE;
 | 
					 | 
				
			||||||
			if (temp_unit == 'F')
 | 
					 | 
				
			||||||
				analog[1].meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				analog[1].meaning->unit = SR_UNIT_CELSIUS;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* AC flag */
 | 
					 | 
				
			||||||
		if (buf[9] & 0x20)  analog[1].meaning->mqflags |= SR_MQFLAG_AC;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* SI prefix */
 | 
					 | 
				
			||||||
		if (buf[ 9] & 0x01)  { floatval[1] *= 1e-6; digits[1] += 6; } /* µ */
 | 
					 | 
				
			||||||
		if (buf[ 9] & 0x02)  { floatval[1] *= 1e-3; digits[1] += 3; } /* m */
 | 
					 | 
				
			||||||
		if (buf[14] & 0x02)  { floatval[1] *= 1e3;  digits[1] -= 3; } /* k */
 | 
					 | 
				
			||||||
		if (buf[14] & 0x01)  { floatval[1] *= 1e6;  digits[1] -= 6; } /* M */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		analog[1].encoding->digits  = digits[1];
 | 
					 | 
				
			||||||
		analog[1].spec->spec_digits = digits[1];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (buf[9] & 0x80)
 | 
					 | 
				
			||||||
		sr_spew("Battery is low.");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void brymen_bm86x_handle_packet(const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
                                       unsigned char *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_datafeed_packet packet;
 | 
					 | 
				
			||||||
	struct sr_datafeed_analog analog[2];
 | 
					 | 
				
			||||||
	struct sr_analog_encoding encoding[2];
 | 
					 | 
				
			||||||
	struct sr_analog_meaning meaning[2];
 | 
					 | 
				
			||||||
	struct sr_analog_spec spec[2];
 | 
					 | 
				
			||||||
	float floatval[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Note: digits/spec_digits will be overridden later. */
 | 
					 | 
				
			||||||
	sr_analog_init(&analog[0], &encoding[0], &meaning[0], &spec[0], 0);
 | 
					 | 
				
			||||||
	sr_analog_init(&analog[1], &encoding[1], &meaning[1], &spec[1], 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	brymen_bm86x_parse(buf, floatval, analog);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (analog[0].meaning->mq != 0) {
 | 
					 | 
				
			||||||
		/* Got a measurement. */
 | 
					 | 
				
			||||||
		analog[0].num_samples = 1;
 | 
					 | 
				
			||||||
		analog[0].data = &floatval[0];
 | 
					 | 
				
			||||||
		analog[0].meaning->channels = g_slist_append(NULL, sdi->channels->data);
 | 
					 | 
				
			||||||
		packet.type = SR_DF_ANALOG;
 | 
					 | 
				
			||||||
		packet.payload = &analog[0];
 | 
					 | 
				
			||||||
		sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
		g_slist_free(analog[0].meaning->channels);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (analog[1].meaning->mq != 0) {
 | 
					 | 
				
			||||||
		/* Got a measurement. */
 | 
					 | 
				
			||||||
		analog[1].num_samples = 1;
 | 
					 | 
				
			||||||
		analog[1].data = &floatval[1];
 | 
					 | 
				
			||||||
		analog[1].meaning->channels = g_slist_append(NULL, sdi->channels->next->data);
 | 
					 | 
				
			||||||
		packet.type = SR_DF_ANALOG;
 | 
					 | 
				
			||||||
		packet.payload = &analog[1];
 | 
					 | 
				
			||||||
		sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
		g_slist_free(analog[1].meaning->channels);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (analog[0].meaning->mq != 0 || analog[1].meaning->mq != 0)
 | 
					 | 
				
			||||||
		sr_sw_limits_update_samples_read(&devc->sw_limits, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int brymen_bm86x_send_command(const struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
					 | 
				
			||||||
	unsigned char buf[] = { 0x00, 0x86, 0x66 };
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	usb = sdi->conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_dbg("Sending HID set report.");
 | 
					 | 
				
			||||||
	ret = libusb_control_transfer(usb->devhdl,
 | 
					 | 
				
			||||||
	                              LIBUSB_REQUEST_TYPE_CLASS |
 | 
					 | 
				
			||||||
	                              LIBUSB_RECIPIENT_INTERFACE |
 | 
					 | 
				
			||||||
	                              LIBUSB_ENDPOINT_OUT,
 | 
					 | 
				
			||||||
	                              9,     /* bRequest: HID set_report */
 | 
					 | 
				
			||||||
	                              0x300, /* wValue: HID feature, report num 0 */
 | 
					 | 
				
			||||||
	                              0,     /* wIndex: interface 0 */
 | 
					 | 
				
			||||||
	                              buf, sizeof(buf), USB_TIMEOUT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		sr_err("HID feature report error: %s.", libusb_error_name(ret));
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret != sizeof(buf)) {
 | 
					 | 
				
			||||||
		sr_err("Short packet: sent %d/%zu bytes.", ret, sizeof(buf));
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int brymen_bm86x_read_interrupt(const struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
					 | 
				
			||||||
	unsigned char buf[24];
 | 
					 | 
				
			||||||
	int ret, transferred;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
	usb = sdi->conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_dbg("Reading HID interrupt report.");
 | 
					 | 
				
			||||||
	/* Get data from EP1 using an interrupt transfer. */
 | 
					 | 
				
			||||||
	ret = libusb_interrupt_transfer(usb->devhdl,
 | 
					 | 
				
			||||||
	                                LIBUSB_ENDPOINT_IN | 1, /* EP1, IN */
 | 
					 | 
				
			||||||
	                                buf, sizeof(buf),
 | 
					 | 
				
			||||||
	                                &transferred, USB_TIMEOUT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret == LIBUSB_ERROR_TIMEOUT) {
 | 
					 | 
				
			||||||
		if (++devc->interrupt_pending > 3)
 | 
					 | 
				
			||||||
			devc->interrupt_pending = 0;
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		sr_err("USB receive error: %s.", libusb_error_name(ret));
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (transferred != sizeof(buf)) {
 | 
					 | 
				
			||||||
		sr_err("Short packet: received %d/%zu bytes.", transferred, sizeof(buf));
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc->interrupt_pending = 0;
 | 
					 | 
				
			||||||
	brymen_bm86x_handle_packet(sdi, buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_bm86x_receive_data(int fd, int revents, void *cb_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)fd;
 | 
					 | 
				
			||||||
	(void)revents;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(sdi = cb_data))
 | 
					 | 
				
			||||||
		return TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(devc = sdi->priv))
 | 
					 | 
				
			||||||
		return TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!devc->interrupt_pending) {
 | 
					 | 
				
			||||||
		if (brymen_bm86x_send_command(sdi))
 | 
					 | 
				
			||||||
			return FALSE;
 | 
					 | 
				
			||||||
		devc->interrupt_pending = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (brymen_bm86x_read_interrupt(sdi))
 | 
					 | 
				
			||||||
		return FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sr_sw_limits_check(&devc->sw_limits))
 | 
					 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,197 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
#include "protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint32_t scanopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_CONN,
 | 
					 | 
				
			||||||
	SR_CONF_SERIALCOMM,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_MULTIMETER,
 | 
					 | 
				
			||||||
	SR_CONF_CONTINUOUS,
 | 
					 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
 | 
					 | 
				
			||||||
	SR_CONF_LIMIT_MSEC | SR_CONF_SET,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GSList *brymen_scan(struct sr_dev_driver *di, const char *conn,
 | 
					 | 
				
			||||||
	const char *serialcomm)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
					 | 
				
			||||||
	GSList *devices;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	uint8_t buf[128];
 | 
					 | 
				
			||||||
	size_t len;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	serial = sr_serial_dev_inst_new(conn, serialcomm);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_info("Probing port %s.", conn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devices = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Request reading */
 | 
					 | 
				
			||||||
	if ((ret = brymen_packet_request(serial)) < 0) {
 | 
					 | 
				
			||||||
		sr_err("Unable to send command: %d.", ret);
 | 
					 | 
				
			||||||
		goto scan_cleanup;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	len = 128;
 | 
					 | 
				
			||||||
	ret = brymen_stream_detect(serial, buf, &len, brymen_packet_length,
 | 
					 | 
				
			||||||
			     brymen_packet_is_valid, 1000, 9600);
 | 
					 | 
				
			||||||
	if (ret != SR_OK)
 | 
					 | 
				
			||||||
		goto scan_cleanup;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_info("Found device on port %s.", conn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
					 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
	sdi->vendor = g_strdup("Brymen");
 | 
					 | 
				
			||||||
	sdi->model = g_strdup("BM85x");
 | 
					 | 
				
			||||||
	devc = g_malloc0(sizeof(struct dev_context));
 | 
					 | 
				
			||||||
	sr_sw_limits_init(&devc->sw_limits);
 | 
					 | 
				
			||||||
	sdi->inst_type = SR_INST_SERIAL;
 | 
					 | 
				
			||||||
	sdi->conn = serial;
 | 
					 | 
				
			||||||
	sdi->priv = devc;
 | 
					 | 
				
			||||||
	sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1");
 | 
					 | 
				
			||||||
	devices = g_slist_append(devices, sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
scan_cleanup:
 | 
					 | 
				
			||||||
	serial_close(serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return std_scan_complete(di, devices);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_config *src;
 | 
					 | 
				
			||||||
	GSList *devices, *l;
 | 
					 | 
				
			||||||
	const char *conn, *serialcomm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devices = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	conn = serialcomm = NULL;
 | 
					 | 
				
			||||||
	for (l = options; l; l = l->next) {
 | 
					 | 
				
			||||||
		src = l->data;
 | 
					 | 
				
			||||||
		switch (src->key) {
 | 
					 | 
				
			||||||
		case SR_CONF_CONN:
 | 
					 | 
				
			||||||
			conn = g_variant_get_string(src->data, NULL);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SR_CONF_SERIALCOMM:
 | 
					 | 
				
			||||||
			serialcomm = g_variant_get_string(src->data, NULL);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!conn)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (serialcomm) {
 | 
					 | 
				
			||||||
		/* Use the provided comm specs. */
 | 
					 | 
				
			||||||
		devices = brymen_scan(di, conn, serialcomm);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* But 9600/8n1 should work all of the time. */
 | 
					 | 
				
			||||||
		devices = brymen_scan(di, conn, "9600/8n1/dtr=1/rts=1");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return devices;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sr_sw_limits_config_set(&devc->sw_limits, key, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->sw_limits);
 | 
					 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Poll every 50ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
					 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 50,
 | 
					 | 
				
			||||||
			brymen_dmm_receive_data, (void *)sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct sr_dev_driver brymen_bm857_driver_info = {
 | 
					 | 
				
			||||||
	.name = "brymen-bm857",
 | 
					 | 
				
			||||||
	.longname = "Brymen BM857",
 | 
					 | 
				
			||||||
	.api_version = 1,
 | 
					 | 
				
			||||||
	.init = std_init,
 | 
					 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
					 | 
				
			||||||
	.scan = scan,
 | 
					 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
					 | 
				
			||||||
	.dev_clear = NULL,
 | 
					 | 
				
			||||||
	.config_get = NULL,
 | 
					 | 
				
			||||||
	.config_set = config_set,
 | 
					 | 
				
			||||||
	.config_list = config_list,
 | 
					 | 
				
			||||||
	.dev_open = std_serial_dev_open,
 | 
					 | 
				
			||||||
	.dev_close = std_serial_dev_close,
 | 
					 | 
				
			||||||
	.dev_acquisition_start = dev_acquisition_start,
 | 
					 | 
				
			||||||
	.dev_acquisition_stop = std_serial_dev_acquisition_stop,
 | 
					 | 
				
			||||||
	.context = NULL,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
SR_REGISTER_DEV_DRIVER(brymen_bm857_driver_info);
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,290 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
#include "protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MAX_PACKET_LEN 22
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Flags passed from the DMM. */
 | 
					 | 
				
			||||||
struct brymen_flags {
 | 
					 | 
				
			||||||
	gboolean is_low_batt, is_decibel, is_duty_cycle, is_hertz, is_amp;
 | 
					 | 
				
			||||||
	gboolean is_beep, is_ohm, is_fahrenheit, is_celsius, is_capacitance;
 | 
					 | 
				
			||||||
	gboolean is_diode, is_volt, is_dc, is_ac;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct bm850_command {
 | 
					 | 
				
			||||||
	uint8_t dle;
 | 
					 | 
				
			||||||
	uint8_t stx;
 | 
					 | 
				
			||||||
	uint8_t cmd;
 | 
					 | 
				
			||||||
	uint8_t arg[2];
 | 
					 | 
				
			||||||
	uint8_t checksum;
 | 
					 | 
				
			||||||
	uint8_t dle2;
 | 
					 | 
				
			||||||
	uint8_t etx;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct brymen_header {
 | 
					 | 
				
			||||||
	uint8_t dle;
 | 
					 | 
				
			||||||
	uint8_t stx;
 | 
					 | 
				
			||||||
	uint8_t cmd;
 | 
					 | 
				
			||||||
	uint8_t len;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct brymen_tail {
 | 
					 | 
				
			||||||
	uint8_t checksum;
 | 
					 | 
				
			||||||
	uint8_t dle;
 | 
					 | 
				
			||||||
	uint8_t etx;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * We only have one command because we only support the BM-857. However, the
 | 
					 | 
				
			||||||
 * driver is easily extensible to support more models, as the protocols are
 | 
					 | 
				
			||||||
 * very similar.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
enum {
 | 
					 | 
				
			||||||
	BM_CMD_REQUEST_READING = 0x00,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int bm_send_command(uint8_t command, uint8_t arg1, uint8_t arg2,
 | 
					 | 
				
			||||||
			   struct sr_serial_dev_inst *serial)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct bm850_command cmdout;
 | 
					 | 
				
			||||||
	int written;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmdout.dle = 0x10;
 | 
					 | 
				
			||||||
	cmdout.stx = 0x02;
 | 
					 | 
				
			||||||
	cmdout.cmd = command;
 | 
					 | 
				
			||||||
	cmdout.arg[0] = arg1;
 | 
					 | 
				
			||||||
	cmdout.arg[1] = arg2;
 | 
					 | 
				
			||||||
	cmdout.checksum = arg1 ^ arg2;
 | 
					 | 
				
			||||||
	cmdout.dle2 = 0x10;
 | 
					 | 
				
			||||||
	cmdout.etx = 0x03;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* TODO: How to compute the checksum? Hardware seems to ignore it. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Request reading. */
 | 
					 | 
				
			||||||
	written = serial_write_blocking(serial, &cmdout, sizeof(cmdout),
 | 
					 | 
				
			||||||
			serial_timeout(serial, sizeof(cmdout)));
 | 
					 | 
				
			||||||
	if (written != sizeof(cmdout))
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return bm_send_command(BM_CMD_REQUEST_READING, 0, 0, serial);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_packet_length(const uint8_t *buf, int *len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct brymen_header *hdr;
 | 
					 | 
				
			||||||
	int packet_len;
 | 
					 | 
				
			||||||
	size_t buflen;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buflen = *len;
 | 
					 | 
				
			||||||
	hdr = (void *)buf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Did we receive a complete header yet? */
 | 
					 | 
				
			||||||
	if (buflen < sizeof(*hdr))
 | 
					 | 
				
			||||||
		return PACKET_NEED_MORE_DATA;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (hdr->dle != 0x10 || hdr->stx != 0x02)
 | 
					 | 
				
			||||||
		return PACKET_INVALID_HEADER;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Our packet includes the header, the payload, and the tail. */
 | 
					 | 
				
			||||||
	packet_len = sizeof(*hdr) + hdr->len + sizeof(struct brymen_tail);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* In case we pick up an invalid header, limit our search. */
 | 
					 | 
				
			||||||
	if (packet_len > MAX_PACKET_LEN) {
 | 
					 | 
				
			||||||
		sr_spew("Header specifies an invalid payload length: %i.",
 | 
					 | 
				
			||||||
			hdr->len);
 | 
					 | 
				
			||||||
		return PACKET_INVALID_HEADER;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*len = packet_len;
 | 
					 | 
				
			||||||
	sr_spew("Expecting a %d-byte packet.", *len);
 | 
					 | 
				
			||||||
	return PACKET_HEADER_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct brymen_header *hdr;
 | 
					 | 
				
			||||||
	struct brymen_tail *tail;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
	uint8_t chksum = 0;
 | 
					 | 
				
			||||||
	uint8_t *payload;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	payload = (uint8_t *)(buf + sizeof(struct brymen_header));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hdr = (void *)buf;
 | 
					 | 
				
			||||||
	tail = (void *)(payload + hdr->len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i< hdr->len; i++)
 | 
					 | 
				
			||||||
		chksum ^= payload[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (tail->checksum != chksum) {
 | 
					 | 
				
			||||||
		sr_dbg("Packet has invalid checksum 0x%.2x. Expected 0x%.2x.",
 | 
					 | 
				
			||||||
		       chksum, tail->checksum);
 | 
					 | 
				
			||||||
		return FALSE;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int parse_value(const char *strbuf, int len, float *floatval)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int s, d;
 | 
					 | 
				
			||||||
	char str[32];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (strstr(strbuf, "OL")) {
 | 
					 | 
				
			||||||
		sr_dbg("Overlimit.");
 | 
					 | 
				
			||||||
		*floatval = INFINITY;
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(str, 0, sizeof(str));
 | 
					 | 
				
			||||||
	/* Spaces may interfere with parsing the exponent. Strip them. */
 | 
					 | 
				
			||||||
	for (s = 0, d = 0; s < len; s++) {
 | 
					 | 
				
			||||||
		if (strbuf[s] != ' ')
 | 
					 | 
				
			||||||
			str[d++] = strbuf[s];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (sr_atof_ascii(str, floatval) != SR_OK)
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void parse_flags(const uint8_t *buf, struct brymen_flags *info)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	info->is_low_batt	= (buf[4 + 3] & (1 << 7)) != 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	info->is_decibel	= (buf[4 + 1] & (1 << 5)) != 0;
 | 
					 | 
				
			||||||
	info->is_duty_cycle	= (buf[4 + 1] & (1 << 3)) != 0;
 | 
					 | 
				
			||||||
	info->is_hertz		= (buf[4 + 1] & (1 << 2)) != 0;
 | 
					 | 
				
			||||||
	info->is_amp		= (buf[4 + 1] & (1 << 1)) != 0;
 | 
					 | 
				
			||||||
	info->is_beep		= (buf[4 + 1] & (1 << 0)) != 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	info->is_ohm		= (buf[4 + 0] & (1 << 7)) != 0;
 | 
					 | 
				
			||||||
	info->is_fahrenheit	= (buf[4 + 0] & (1 << 6)) != 0;
 | 
					 | 
				
			||||||
	info->is_celsius	= (buf[4 + 0] & (1 << 5)) != 0;
 | 
					 | 
				
			||||||
	info->is_diode		= (buf[4 + 0] & (1 << 4)) != 0;
 | 
					 | 
				
			||||||
	info->is_capacitance	= (buf[4 + 0] & (1 << 3)) != 0;
 | 
					 | 
				
			||||||
	info->is_volt		= (buf[4 + 0] & (1 << 2)) != 0;
 | 
					 | 
				
			||||||
	info->is_dc		= (buf[4 + 0] & (1 << 1)) != 0;
 | 
					 | 
				
			||||||
	info->is_ac		= (buf[4 + 0] & (1 << 0)) != 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_parse(const uint8_t *buf, float *floatval,
 | 
					 | 
				
			||||||
		struct sr_datafeed_analog *analog, void *info)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct brymen_flags flags;
 | 
					 | 
				
			||||||
	struct brymen_header *hdr;
 | 
					 | 
				
			||||||
	uint8_t *bfunc;
 | 
					 | 
				
			||||||
	int asciilen;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)info;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hdr = (void *)buf;
 | 
					 | 
				
			||||||
	bfunc = (uint8_t *)(buf + sizeof(struct brymen_header));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	analog->meaning->mqflags = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Give some debug info about the package. */
 | 
					 | 
				
			||||||
	asciilen = hdr->len - 4;
 | 
					 | 
				
			||||||
	sr_dbg("DMM flags: %.2x %.2x %.2x %.2x",
 | 
					 | 
				
			||||||
	       bfunc[3], bfunc[2], bfunc[1], bfunc[0]);
 | 
					 | 
				
			||||||
	/* Value is an ASCII string. */
 | 
					 | 
				
			||||||
	sr_dbg("DMM packet: \"%.*s\"", asciilen, bfunc + 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	parse_flags(buf, &flags);
 | 
					 | 
				
			||||||
	if (parse_value((const char *)(bfunc + 4), asciilen, floatval) != SR_OK)
 | 
					 | 
				
			||||||
		return SR_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (flags.is_volt) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_VOLTAGE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_VOLT;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_amp) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_CURRENT;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_AMPERE;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_ohm) {
 | 
					 | 
				
			||||||
		if (flags.is_beep)
 | 
					 | 
				
			||||||
			analog->meaning->mq = SR_MQ_CONTINUITY;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			analog->meaning->mq = SR_MQ_RESISTANCE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_OHM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_hertz) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_FREQUENCY;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_HERTZ;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_duty_cycle) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_DUTY_CYCLE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_PERCENTAGE;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_capacitance) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_FARAD;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_fahrenheit) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_FAHRENHEIT;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_celsius) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_TEMPERATURE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_CELSIUS;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (flags.is_capacitance) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_CAPACITANCE;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_FARAD;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * The high-end Brymen models have a configurable reference impedance.
 | 
					 | 
				
			||||||
	 * When the reference impedance is changed, the DMM sends one packet
 | 
					 | 
				
			||||||
	 * with the value of the new reference impedance. Both decibel and ohm
 | 
					 | 
				
			||||||
	 * flags are set in this case, so we must be careful to correctly
 | 
					 | 
				
			||||||
	 * identify the value as ohm, not dBmW.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (flags.is_decibel && !flags.is_ohm) {
 | 
					 | 
				
			||||||
		analog->meaning->mq = SR_MQ_POWER;
 | 
					 | 
				
			||||||
		analog->meaning->unit = SR_UNIT_DECIBEL_MW;
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * For some reason, dBm measurements are sent by the multimeter
 | 
					 | 
				
			||||||
		 * with a value three orders of magnitude smaller than the
 | 
					 | 
				
			||||||
		 * displayed value.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		*floatval *= 1000;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (flags.is_diode)
 | 
					 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DIODE;
 | 
					 | 
				
			||||||
	/* We can have both AC+DC in a single measurement. */
 | 
					 | 
				
			||||||
	if (flags.is_ac)
 | 
					 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_AC;
 | 
					 | 
				
			||||||
	if (flags.is_dc)
 | 
					 | 
				
			||||||
		analog->meaning->mqflags |= SR_MQFLAG_DC;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (flags.is_low_batt)
 | 
					 | 
				
			||||||
		sr_info("Low battery!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,256 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					 | 
				
			||||||
#include "protocol.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	float floatval;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_datafeed_packet packet;
 | 
					 | 
				
			||||||
	struct sr_datafeed_analog analog;
 | 
					 | 
				
			||||||
	struct sr_analog_encoding encoding;
 | 
					 | 
				
			||||||
	struct sr_analog_meaning meaning;
 | 
					 | 
				
			||||||
	struct sr_analog_spec spec;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* TODO: Use proper 'digits' value for this device (and its modes). */
 | 
					 | 
				
			||||||
	sr_analog_init(&analog, &encoding, &meaning, &spec, 2);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	analog.num_samples = 1;
 | 
					 | 
				
			||||||
	analog.meaning->mq = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	analog.data = &floatval;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	analog.meaning->channels = sdi->channels;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (analog.meaning->mq != 0) {
 | 
					 | 
				
			||||||
		/* Got a measurement. */
 | 
					 | 
				
			||||||
		packet.type = SR_DF_ANALOG;
 | 
					 | 
				
			||||||
		packet.payload = &analog;
 | 
					 | 
				
			||||||
		sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
		sr_sw_limits_update_samples_read(&devc->sw_limits, 1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void handle_new_data(struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	int len, status, offset = 0;
 | 
					 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Try to get as much data as the buffer can hold. */
 | 
					 | 
				
			||||||
	len = DMM_BUFSIZE - devc->buflen;
 | 
					 | 
				
			||||||
	len = serial_read_nonblocking(serial, devc->buf + devc->buflen, len);
 | 
					 | 
				
			||||||
	if (len < 1) {
 | 
					 | 
				
			||||||
		sr_err("Serial port read error: %d.", len);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	devc->buflen += len;
 | 
					 | 
				
			||||||
	status = PACKET_INVALID_HEADER;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Now look for packets in that data. */
 | 
					 | 
				
			||||||
	while (status != PACKET_NEED_MORE_DATA) {
 | 
					 | 
				
			||||||
		/* We don't have a header, look for one. */
 | 
					 | 
				
			||||||
		if (devc->next_packet_len == 0) {
 | 
					 | 
				
			||||||
			len = devc->buflen - offset;
 | 
					 | 
				
			||||||
			status = brymen_packet_length(devc->buf + offset, &len);
 | 
					 | 
				
			||||||
			if (status == PACKET_HEADER_OK) {
 | 
					 | 
				
			||||||
				/* We know how large the packet will be. */
 | 
					 | 
				
			||||||
				devc->next_packet_len = len;
 | 
					 | 
				
			||||||
			} else if (status == PACKET_NEED_MORE_DATA) {
 | 
					 | 
				
			||||||
				/* We didn't yet receive the full header. */
 | 
					 | 
				
			||||||
				devc->next_packet_len = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				/* Invalid header. Move on. */
 | 
					 | 
				
			||||||
				devc->next_packet_len = 0;
 | 
					 | 
				
			||||||
				offset++;
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* We know how the packet size, but did we receive all of it? */
 | 
					 | 
				
			||||||
		if (devc->buflen - offset < devc->next_packet_len)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* We should have a full packet here, so we can check it. */
 | 
					 | 
				
			||||||
		if (brymen_packet_is_valid(devc->buf + offset)) {
 | 
					 | 
				
			||||||
			handle_packet(devc->buf + offset, sdi);
 | 
					 | 
				
			||||||
			offset += devc->next_packet_len;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			offset++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* We are done with this packet. Look for a new one. */
 | 
					 | 
				
			||||||
		devc->next_packet_len = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If we have any data left, move it to the beginning of our buffer. */
 | 
					 | 
				
			||||||
	memmove(devc->buf, devc->buf + offset, devc->buflen - offset);
 | 
					 | 
				
			||||||
	devc->buflen -= offset;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(sdi = cb_data))
 | 
					 | 
				
			||||||
		return TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(devc = sdi->priv))
 | 
					 | 
				
			||||||
		return TRUE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (revents == G_IO_IN) {
 | 
					 | 
				
			||||||
		/* Serial data arrived. */
 | 
					 | 
				
			||||||
		handle_new_data(sdi);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* Timeout, send another packet request. */
 | 
					 | 
				
			||||||
		if ((ret = brymen_packet_request(serial)) < 0) {
 | 
					 | 
				
			||||||
			sr_err("Failed to request packet: %d.", ret);
 | 
					 | 
				
			||||||
			return FALSE;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sr_sw_limits_check(&devc->sw_limits))
 | 
					 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return TRUE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Try to find a valid packet in a serial data stream.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param serial Previously initialized serial port structure.
 | 
					 | 
				
			||||||
 * @param buf Buffer containing the bytes to write.
 | 
					 | 
				
			||||||
 * @param buflen Size of the buffer.
 | 
					 | 
				
			||||||
 * @param get_packet_size Callback that assesses the size of incoming packets.
 | 
					 | 
				
			||||||
 * @param is_valid Callback that assesses whether the packet is valid or not.
 | 
					 | 
				
			||||||
 * @param timeout_ms The timeout after which, if no packet is detected, to
 | 
					 | 
				
			||||||
 *                   abort scanning.
 | 
					 | 
				
			||||||
 * @param baudrate The baudrate of the serial port. This parameter is not
 | 
					 | 
				
			||||||
 *                 critical, but it helps fine tune the serial port polling
 | 
					 | 
				
			||||||
 *                 delay.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return SR_OK if a valid packet is found within the given timeout,
 | 
					 | 
				
			||||||
 *         SR_ERR upon failure.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
 | 
					 | 
				
			||||||
				uint8_t *buf, size_t *buflen,
 | 
					 | 
				
			||||||
				packet_length_t get_packet_size,
 | 
					 | 
				
			||||||
				packet_valid_callback is_valid,
 | 
					 | 
				
			||||||
				uint64_t timeout_ms, int baudrate)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int64_t start, time, byte_delay_us;
 | 
					 | 
				
			||||||
	size_t ibuf, i, maxlen;
 | 
					 | 
				
			||||||
	ssize_t len, stream_len;
 | 
					 | 
				
			||||||
	int packet_len;
 | 
					 | 
				
			||||||
	int status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	maxlen = *buflen;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_dbg("Detecting packets on %s (timeout = %" PRIu64
 | 
					 | 
				
			||||||
	       "ms, baudrate = %d).", serial->port, timeout_ms, baudrate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Assume 8n1 transmission. That is 10 bits for every byte. */
 | 
					 | 
				
			||||||
	byte_delay_us = 10 * ((1000 * 1000) / baudrate);
 | 
					 | 
				
			||||||
	start = g_get_monotonic_time();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	packet_len = i = ibuf = len = 0;
 | 
					 | 
				
			||||||
	while (ibuf < maxlen) {
 | 
					 | 
				
			||||||
		len = serial_read_nonblocking(serial, &buf[ibuf], maxlen - ibuf);
 | 
					 | 
				
			||||||
		if (len > 0) {
 | 
					 | 
				
			||||||
			ibuf += len;
 | 
					 | 
				
			||||||
			sr_spew("Read %zd bytes.", len);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		time = g_get_monotonic_time() - start;
 | 
					 | 
				
			||||||
		time /= 1000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		stream_len = ibuf - i;
 | 
					 | 
				
			||||||
		if (stream_len > 0 && packet_len == 0) {
 | 
					 | 
				
			||||||
			/* How large of a packet are we expecting? */
 | 
					 | 
				
			||||||
			packet_len = stream_len;
 | 
					 | 
				
			||||||
			status = get_packet_size(&buf[i], &packet_len);
 | 
					 | 
				
			||||||
			switch (status) {
 | 
					 | 
				
			||||||
			case PACKET_HEADER_OK:
 | 
					 | 
				
			||||||
				/* We know how much data we need to wait for. */
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case PACKET_NEED_MORE_DATA:
 | 
					 | 
				
			||||||
				/* We did not receive the full header. */
 | 
					 | 
				
			||||||
				packet_len = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case PACKET_INVALID_HEADER:
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				/*
 | 
					 | 
				
			||||||
				 * We had enough data, but here was an error in
 | 
					 | 
				
			||||||
				 * parsing the header. Restart parsing from the
 | 
					 | 
				
			||||||
				 * next byte.
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				packet_len = 0;
 | 
					 | 
				
			||||||
				i++;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((stream_len >= packet_len) && (packet_len != 0)) {
 | 
					 | 
				
			||||||
			/* We have at least a packet's worth of data. */
 | 
					 | 
				
			||||||
			if (is_valid(&buf[i])) {
 | 
					 | 
				
			||||||
				sr_spew("Found valid %d-byte packet after "
 | 
					 | 
				
			||||||
					"%" PRIu64 "ms.", packet_len, time);
 | 
					 | 
				
			||||||
				*buflen = ibuf;
 | 
					 | 
				
			||||||
				return SR_OK;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				sr_spew("Got %d bytes, but not a valid "
 | 
					 | 
				
			||||||
					"packet.", packet_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Not a valid packet. Continue searching. */
 | 
					 | 
				
			||||||
			i++;
 | 
					 | 
				
			||||||
			packet_len = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (time >= (int64_t)timeout_ms) {
 | 
					 | 
				
			||||||
			/* Timeout */
 | 
					 | 
				
			||||||
			sr_dbg("Detection timed out after %" PRIi64 "ms.", time);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		g_usleep(byte_delay_us);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*buflen = ibuf;
 | 
					 | 
				
			||||||
	sr_err("Didn't find a valid packet (read %zu bytes).", ibuf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_ERR;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,75 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * This file is part of the libsigrok project.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
 * it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
 * (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef LIBSIGROK_HARDWARE_BRYMEN_DMM_PROTOCOL_H
 | 
					 | 
				
			||||||
#define LIBSIGROK_HARDWARE_BRYMEN_DMM_PROTOCOL_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdint.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <math.h>
 | 
					 | 
				
			||||||
#include <glib.h>
 | 
					 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define LOG_PREFIX "brymen-dmm"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DMM_BUFSIZE 256
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum packet_len_status {
 | 
					 | 
				
			||||||
	PACKET_HEADER_OK,
 | 
					 | 
				
			||||||
	PACKET_NEED_MORE_DATA,
 | 
					 | 
				
			||||||
	PACKET_INVALID_HEADER,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					 | 
				
			||||||
	struct sr_sw_limits sw_limits;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint8_t buf[DMM_BUFSIZE];
 | 
					 | 
				
			||||||
	int bufoffset;
 | 
					 | 
				
			||||||
	int buflen;
 | 
					 | 
				
			||||||
	int next_packet_len;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Callback that assesses the size and status of the incoming packet.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @return PACKET_HEADER_OK - This is a proper packet header.
 | 
					 | 
				
			||||||
 *         PACKET_NEED_MORE_DATA The buffer does not contain the entire header.
 | 
					 | 
				
			||||||
 *         PACKET_INVALID_HEADER Not a valid start of packet.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef int (*packet_length_t)(const uint8_t *buf, int *len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data);
 | 
					 | 
				
			||||||
SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_packet_length(const uint8_t *buf, int *len);
 | 
					 | 
				
			||||||
SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_parse(const uint8_t *buf, float *floatval,
 | 
					 | 
				
			||||||
		struct sr_datafeed_analog *analog, void *info);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
 | 
					 | 
				
			||||||
				 uint8_t *buf, size_t *buflen,
 | 
					 | 
				
			||||||
				 packet_length_t get_packet_size,
 | 
					 | 
				
			||||||
				 packet_valid_callback is_valid,
 | 
					 | 
				
			||||||
				 uint64_t timeout_ms, int baudrate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -125,11 +125,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	return std_scan_complete(di, devices);
 | 
						return std_scan_complete(di, devices);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	GVariant *range[2];
 | 
					 | 
				
			||||||
	uint64_t low, high;
 | 
						uint64_t low, high;
 | 
				
			||||||
	int tmp, ret;
 | 
						int tmp, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,7 +138,9 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
		return SR_ERR_ARG;
 | 
							return SR_ERR_ARG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
						ret = SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		*data = g_variant_new_uint64(devc->limit_samples);
 | 
							*data = g_variant_new_uint64(devc->limit_samples);
 | 
				
			||||||
| 
						 | 
					@ -175,11 +176,8 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
			*data = g_variant_new_boolean(tmp == SR_MQFLAG_MIN);
 | 
								*data = g_variant_new_boolean(tmp == SR_MQFLAG_MIN);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
						case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
				
			||||||
		if ((ret = cem_dt_885x_meas_range_get(sdi, &low, &high)) == SR_OK) {
 | 
							if ((ret = cem_dt_885x_meas_range_get(sdi, &low, &high)) == SR_OK)
 | 
				
			||||||
			range[0] = g_variant_new_uint64(low);
 | 
								*data = std_gvar_tuple_u64(low, high);
 | 
				
			||||||
			range[1] = g_variant_new_uint64(high);
 | 
					 | 
				
			||||||
			*data = g_variant_new_tuple(range, 2);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_POWER_OFF:
 | 
						case SR_CONF_POWER_OFF:
 | 
				
			||||||
		*data = g_variant_new_boolean(FALSE);
 | 
							*data = g_variant_new_boolean(FALSE);
 | 
				
			||||||
| 
						 | 
					@ -197,148 +195,83 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	uint64_t tmp_u64, low, high;
 | 
						int tmp, idx;
 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
	int tmp, ret;
 | 
					 | 
				
			||||||
	const char *tmp_str;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		tmp_u64 = g_variant_get_uint64(data);
 | 
							devc->limit_samples = g_variant_get_uint64(data);
 | 
				
			||||||
		devc->limit_samples = tmp_u64;
 | 
					 | 
				
			||||||
		ret = SR_OK;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_DATALOG:
 | 
						case SR_CONF_DATALOG:
 | 
				
			||||||
		ret = cem_dt_885x_recording_set(sdi, g_variant_get_boolean(data));
 | 
							return cem_dt_885x_recording_set(sdi, g_variant_get_boolean(data));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SPL_WEIGHT_FREQ:
 | 
						case SR_CONF_SPL_WEIGHT_FREQ:
 | 
				
			||||||
		tmp_str = g_variant_get_string(data, NULL);
 | 
							if ((idx = std_str_idx(data, ARRAY_AND_SIZE(weight_freq))) < 0)
 | 
				
			||||||
		if (!strcmp(tmp_str, "A"))
 | 
					 | 
				
			||||||
			ret = cem_dt_885x_weight_freq_set(sdi,
 | 
					 | 
				
			||||||
					SR_MQFLAG_SPL_FREQ_WEIGHT_A);
 | 
					 | 
				
			||||||
		else if (!strcmp(tmp_str, "C"))
 | 
					 | 
				
			||||||
			ret = cem_dt_885x_weight_freq_set(sdi,
 | 
					 | 
				
			||||||
					SR_MQFLAG_SPL_FREQ_WEIGHT_C);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		break;
 | 
							return cem_dt_885x_weight_freq_set(sdi, (weight_freq[idx][0] == 'A') ?
 | 
				
			||||||
 | 
								SR_MQFLAG_SPL_FREQ_WEIGHT_A : SR_MQFLAG_SPL_FREQ_WEIGHT_C);
 | 
				
			||||||
	case SR_CONF_SPL_WEIGHT_TIME:
 | 
						case SR_CONF_SPL_WEIGHT_TIME:
 | 
				
			||||||
		tmp_str = g_variant_get_string(data, NULL);
 | 
							if ((idx = std_str_idx(data, ARRAY_AND_SIZE(weight_time))) < 0)
 | 
				
			||||||
		if (!strcmp(tmp_str, "F"))
 | 
					 | 
				
			||||||
			ret = cem_dt_885x_weight_time_set(sdi,
 | 
					 | 
				
			||||||
					SR_MQFLAG_SPL_TIME_WEIGHT_F);
 | 
					 | 
				
			||||||
		else if (!strcmp(tmp_str, "S"))
 | 
					 | 
				
			||||||
			ret = cem_dt_885x_weight_time_set(sdi,
 | 
					 | 
				
			||||||
					SR_MQFLAG_SPL_TIME_WEIGHT_S);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		break;
 | 
							return cem_dt_885x_weight_time_set(sdi, (weight_time[idx][0] == 'F') ?
 | 
				
			||||||
 | 
								SR_MQFLAG_SPL_TIME_WEIGHT_F : SR_MQFLAG_SPL_TIME_WEIGHT_S);
 | 
				
			||||||
	case SR_CONF_HOLD_MAX:
 | 
						case SR_CONF_HOLD_MAX:
 | 
				
			||||||
		tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MAX : 0;
 | 
							tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MAX : 0;
 | 
				
			||||||
		ret = cem_dt_885x_holdmode_set(sdi, tmp);
 | 
							return cem_dt_885x_holdmode_set(sdi, tmp);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_HOLD_MIN:
 | 
						case SR_CONF_HOLD_MIN:
 | 
				
			||||||
		tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MIN : 0;
 | 
							tmp = g_variant_get_boolean(data) ? SR_MQFLAG_MIN : 0;
 | 
				
			||||||
		ret = cem_dt_885x_holdmode_set(sdi, tmp);
 | 
							return cem_dt_885x_holdmode_set(sdi, tmp);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
						case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
				
			||||||
		g_variant_get(data, "(tt)", &low, &high);
 | 
							if ((idx = std_u64_tuple_idx(data, ARRAY_AND_SIZE(meas_ranges))) < 0)
 | 
				
			||||||
		ret = SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) {
 | 
							return cem_dt_885x_meas_range_set(sdi, meas_ranges[idx][0], meas_ranges[idx][1]);
 | 
				
			||||||
			if (meas_ranges[i][0] == low && meas_ranges[i][1] == high) {
 | 
					 | 
				
			||||||
				ret = cem_dt_885x_meas_range_set(sdi, low, high);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_POWER_OFF:
 | 
						case SR_CONF_POWER_OFF:
 | 
				
			||||||
		if (g_variant_get_boolean(data))
 | 
							if (g_variant_get_boolean(data))
 | 
				
			||||||
			ret = cem_dt_885x_power_off(sdi);
 | 
								return cem_dt_885x_power_off(sdi);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_DATA_SOURCE:
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
		tmp_str = g_variant_get_string(data, NULL);
 | 
							if ((idx = std_str_idx(data, ARRAY_AND_SIZE(data_sources))) < 0)
 | 
				
			||||||
		if (!strcmp(tmp_str, "Live"))
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
			devc->cur_data_source = DATA_SOURCE_LIVE;
 | 
							devc->cur_data_source = idx;
 | 
				
			||||||
		else if (!strcmp(tmp_str, "Memory"))
 | 
							devc->enable_data_source_memory = (idx == DATA_SOURCE_MEMORY);
 | 
				
			||||||
			devc->cur_data_source = DATA_SOURCE_MEMORY;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			return SR_ERR;
 | 
					 | 
				
			||||||
		devc->enable_data_source_memory = devc->cur_data_source == DATA_SOURCE_MEMORY;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GVariant *tuple, *range[2];
 | 
					 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
	unsigned int i;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	if (!sdi) {
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
					drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return SR_ERR_NA;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		switch (key) {
 | 
					 | 
				
			||||||
		case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
	case SR_CONF_SPL_WEIGHT_FREQ:
 | 
						case SR_CONF_SPL_WEIGHT_FREQ:
 | 
				
			||||||
			*data = g_variant_new_strv(weight_freq, ARRAY_SIZE(weight_freq));
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(weight_freq));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_SPL_WEIGHT_TIME:
 | 
						case SR_CONF_SPL_WEIGHT_TIME:
 | 
				
			||||||
			*data = g_variant_new_strv(weight_time, ARRAY_SIZE(weight_time));
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(weight_time));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
						case SR_CONF_SPL_MEASUREMENT_RANGE:
 | 
				
			||||||
			g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
 | 
							*data = std_gvar_tuple_array(ARRAY_AND_SIZE(meas_ranges));
 | 
				
			||||||
			for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) {
 | 
					 | 
				
			||||||
				range[0] = g_variant_new_uint64(meas_ranges[i][0]);
 | 
					 | 
				
			||||||
				range[1] = g_variant_new_uint64(meas_ranges[i][1]);
 | 
					 | 
				
			||||||
				tuple = g_variant_new_tuple(range, 2);
 | 
					 | 
				
			||||||
				g_variant_builder_add_value(&gvb, tuple);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_DATA_SOURCE:
 | 
						case SR_CONF_DATA_SOURCE:
 | 
				
			||||||
			*data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
 | 
							*data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -346,9 +279,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	devc->state = ST_INIT;
 | 
						devc->state = ST_INIT;
 | 
				
			||||||
	devc->num_samples = 0;
 | 
						devc->num_samples = 0;
 | 
				
			||||||
| 
						 | 
					@ -356,7 +286,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 100ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 150,
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 150,
 | 
				
			||||||
			cem_dt_885x_receive_data, (void *)sdi);
 | 
								cem_dt_885x_receive_data, (void *)sdi);
 | 
				
			||||||
| 
						 | 
					@ -372,7 +301,7 @@ static struct sr_dev_driver cem_dt_885x_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = config_get,
 | 
						.config_get = config_get,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ static void process_mset(const struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		devc->num_samples++;
 | 
							devc->num_samples++;
 | 
				
			||||||
		if (devc->limit_samples && devc->num_samples >= devc->limit_samples)
 | 
							if (devc->limit_samples && devc->num_samples >= devc->limit_samples)
 | 
				
			||||||
			sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
								sr_dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case TOKEN_RECORDING_ON:
 | 
						case TOKEN_RECORDING_ON:
 | 
				
			||||||
		devc->recording = TRUE;
 | 
							devc->recording = TRUE;
 | 
				
			||||||
| 
						 | 
					@ -208,7 +208,7 @@ static void send_data(const struct sr_dev_inst *sdi, unsigned char *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc->num_samples += analog.num_samples;
 | 
						devc->num_samples += analog.num_samples;
 | 
				
			||||||
	if (devc->limit_samples && devc->num_samples >= devc->limit_samples)
 | 
						if (devc->limit_samples && devc->num_samples >= devc->limit_samples)
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
							sr_dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -321,7 +321,7 @@ static void process_byte(const struct sr_dev_inst *sdi, const unsigned char c,
 | 
				
			||||||
			 * records. Otherwise the frontend would have no
 | 
								 * records. Otherwise the frontend would have no
 | 
				
			||||||
			 * way to tell where stored data ends and live
 | 
								 * way to tell where stored data ends and live
 | 
				
			||||||
			 * measurements begin. */
 | 
								 * measurements begin. */
 | 
				
			||||||
			sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
								sr_dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
				
			||||||
		} else if (c == RECORD_DATA) {
 | 
							} else if (c == RECORD_DATA) {
 | 
				
			||||||
			devc->buf_len = 0;
 | 
								devc->buf_len = 0;
 | 
				
			||||||
			devc->state = ST_GET_LOG_RECORD_DATA;
 | 
								devc->state = ST_GET_LOG_RECORD_DATA;
 | 
				
			||||||
| 
						 | 
					@ -346,7 +346,8 @@ static void process_byte(const struct sr_dev_inst *sdi, const unsigned char c,
 | 
				
			||||||
					g_variant_new_uint64(devc->buf[7] * 1000));
 | 
										g_variant_new_uint64(devc->buf[7] * 1000));
 | 
				
			||||||
			meta.config = g_slist_append(NULL, src);
 | 
								meta.config = g_slist_append(NULL, src);
 | 
				
			||||||
			sr_session_send(sdi, &packet);
 | 
								sr_session_send(sdi, &packet);
 | 
				
			||||||
			g_free(src);
 | 
								g_slist_free(meta.config);
 | 
				
			||||||
 | 
								sr_config_free(src);
 | 
				
			||||||
			devc->buf_len = 0;
 | 
								devc->buf_len = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (devc->state == ST_GET_LOG_RECORD_DATA) {
 | 
						} else if (devc->state == ST_GET_LOG_RECORD_DATA) {
 | 
				
			||||||
| 
						 | 
					@ -400,7 +401,7 @@ SR_PRIV int cem_dt_885x_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				/* Tell device to start transferring from memory. */
 | 
									/* Tell device to start transferring from memory. */
 | 
				
			||||||
				cmd = CMD_TRANSFER_MEMORY;
 | 
									cmd = CMD_TRANSFER_MEMORY;
 | 
				
			||||||
				serial_write_nonblocking(serial, &cmd, 1);
 | 
									serial_write_blocking(serial, &cmd, 1, 0);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -456,7 +457,7 @@ static int cem_dt_885x_toggle(const struct sr_dev_inst *sdi, uint8_t cmd,
 | 
				
			||||||
	 * only thing to do is wait for the token that will confirm
 | 
						 * only thing to do is wait for the token that will confirm
 | 
				
			||||||
	 * whether the command worked or not, and resend if needed. */
 | 
						 * whether the command worked or not, and resend if needed. */
 | 
				
			||||||
	while (TRUE) {
 | 
						while (TRUE) {
 | 
				
			||||||
		if (serial_write_nonblocking(serial, (const void *)&cmd, 1) != 1)
 | 
							if (serial_write_blocking(serial, (const void *)&cmd, 1, 0) < 0)
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
		if (wait_for_token(sdi, tokens, timeout) == SR_ERR)
 | 
							if (wait_for_token(sdi, tokens, timeout) == SR_ERR)
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
| 
						 | 
					@ -817,7 +818,7 @@ SR_PRIV int cem_dt_885x_power_off(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	cmd = CMD_TOGGLE_POWER_OFF;
 | 
						cmd = CMD_TOGGLE_POWER_OFF;
 | 
				
			||||||
	while (TRUE) {
 | 
						while (TRUE) {
 | 
				
			||||||
		serial_flush(serial);
 | 
							serial_flush(serial);
 | 
				
			||||||
		if (serial_write_nonblocking(serial, (const void *)&cmd, 1) != 1)
 | 
							if (serial_write_blocking(serial, (const void *)&cmd, 1, 0) < 0)
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
		/* It never takes more than 23ms for the next token to arrive. */
 | 
							/* It never takes more than 23ms for the next token to arrive. */
 | 
				
			||||||
		g_usleep(25 * 1000);
 | 
							g_usleep(25 * 1000);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,23 +87,18 @@ enum {
 | 
				
			||||||
	DATA_SOURCE_MEMORY,
 | 
						DATA_SOURCE_MEMORY,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	/* Device state */
 | 
					 | 
				
			||||||
	enum sr_mqflag cur_mqflags;
 | 
						enum sr_mqflag cur_mqflags;
 | 
				
			||||||
	int recording;
 | 
						int recording;
 | 
				
			||||||
	int cur_meas_range;
 | 
						int cur_meas_range;
 | 
				
			||||||
	int cur_data_source;
 | 
						int cur_data_source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Acquisition settings */
 | 
					 | 
				
			||||||
	uint64_t limit_samples;
 | 
						uint64_t limit_samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Operational state */
 | 
					 | 
				
			||||||
	int state;
 | 
						int state;
 | 
				
			||||||
	uint64_t num_samples;
 | 
						uint64_t num_samples;
 | 
				
			||||||
	gboolean enable_data_source_memory;
 | 
						gboolean enable_data_source_memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Temporary state across callbacks */
 | 
					 | 
				
			||||||
	unsigned char cmd;
 | 
						unsigned char cmd;
 | 
				
			||||||
	unsigned char token;
 | 
						unsigned char token;
 | 
				
			||||||
	int buf_len;
 | 
						int buf_len;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,8 +67,6 @@ static GSList *center_scan(const char *conn, const char *serialcomm, int idx)
 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
						if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_info("Found device on port %s.", conn);
 | 
						sr_info("Found device on port %s.", conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
						sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
				
			||||||
| 
						 | 
					@ -109,55 +107,30 @@ static GSList *scan(GSList *options, int idx)
 | 
				
			||||||
	if (!conn)
 | 
						if (!conn)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (serialcomm) {
 | 
						if (serialcomm)
 | 
				
			||||||
		/* Use the provided comm specs. */
 | 
					 | 
				
			||||||
		devices = center_scan(conn, serialcomm, idx);
 | 
							devices = center_scan(conn, serialcomm, idx);
 | 
				
			||||||
	} else {
 | 
						else
 | 
				
			||||||
		/* Try the default. */
 | 
					 | 
				
			||||||
		devices = center_scan(conn, center_devs[idx].conn, idx);
 | 
							devices = center_scan(conn, center_devs[idx].conn, idx);
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return std_scan_complete(center_devs[idx].di, devices);
 | 
						return std_scan_complete(center_devs[idx].di, devices);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sr_sw_limits_config_set(&devc->sw_limits, key, data);
 | 
						return sr_sw_limits_config_set(&devc->sw_limits, key, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	(void)cg;
 | 
						return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		if (!sdi)
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi, int idx)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi, int idx)
 | 
				
			||||||
| 
						 | 
					@ -165,16 +138,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, int idx)
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->sw_limits);
 | 
						sr_sw_limits_acquisition_start(&devc->sw_limits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 500ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 500,
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 500,
 | 
				
			||||||
		      center_devs[idx].receive_data, (void *)sdi);
 | 
							      center_devs[idx].receive_data, (void *)sdi);
 | 
				
			||||||
| 
						 | 
					@ -202,6 +171,7 @@ static struct sr_dev_driver ID##_driver_info = { \
 | 
				
			||||||
	.cleanup = std_cleanup, \
 | 
						.cleanup = std_cleanup, \
 | 
				
			||||||
	.scan = scan_##ID_UPPER, \
 | 
						.scan = scan_##ID_UPPER, \
 | 
				
			||||||
	.dev_list = std_dev_list, \
 | 
						.dev_list = std_dev_list, \
 | 
				
			||||||
 | 
						.dev_clear = std_dev_clear, \
 | 
				
			||||||
	.config_get = NULL, \
 | 
						.config_get = NULL, \
 | 
				
			||||||
	.config_set = config_set, \
 | 
						.config_set = config_set, \
 | 
				
			||||||
	.config_list = config_list, \
 | 
						.config_list = config_list, \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ static void log_packet(const uint8_t *buf, int idx)
 | 
				
			||||||
static int packet_parse(const uint8_t *buf, int idx, struct center_info *info)
 | 
					static int packet_parse(const uint8_t *buf, int idx, struct center_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	uint16_t temp_u16;
 | 
						int16_t temp_i16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log_packet(buf, idx);
 | 
						log_packet(buf, idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,9 +89,8 @@ static int packet_parse(const uint8_t *buf, int idx, struct center_info *info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Byte 7+8/9+10/11+12/13+14: channel T1/T2/T3/T4 temperature. */
 | 
						/* Byte 7+8/9+10/11+12/13+14: channel T1/T2/T3/T4 temperature. */
 | 
				
			||||||
	for (i = 0; i < NUM_CHANNELS; i++) {
 | 
						for (i = 0; i < NUM_CHANNELS; i++) {
 | 
				
			||||||
		temp_u16 = buf[8 + (i * 2)];
 | 
							temp_i16 = RB16S(&buf[7 + 2 * i]);
 | 
				
			||||||
		temp_u16 |= ((uint16_t)buf[7 + (i * 2)] << 8);
 | 
							info->temp[i] = (float)temp_i16;
 | 
				
			||||||
		info->temp[i] = (float)temp_u16;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Byte 43: Specifies whether we need to divide the value(s) by 10. */
 | 
						/* Byte 43: Specifies whether we need to divide the value(s) by 10. */
 | 
				
			||||||
| 
						 | 
					@ -177,7 +176,7 @@ static gboolean handle_new_data(struct sr_dev_inst *sdi, int idx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
	int len, i, offset = 0, ret = FALSE;
 | 
						int len, offset, ret = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
| 
						 | 
					@ -193,6 +192,7 @@ static gboolean handle_new_data(struct sr_dev_inst *sdi, int idx)
 | 
				
			||||||
	devc->buflen += len;
 | 
						devc->buflen += len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Now look for packets in that data. */
 | 
						/* Now look for packets in that data. */
 | 
				
			||||||
 | 
						offset = 0;
 | 
				
			||||||
	while ((devc->buflen - offset) >= center_devs[idx].packet_size) {
 | 
						while ((devc->buflen - offset) >= center_devs[idx].packet_size) {
 | 
				
			||||||
		if (center_devs[idx].packet_valid(devc->buf + offset)) {
 | 
							if (center_devs[idx].packet_valid(devc->buf + offset)) {
 | 
				
			||||||
			handle_packet(devc->buf + offset, sdi, idx);
 | 
								handle_packet(devc->buf + offset, sdi, idx);
 | 
				
			||||||
| 
						 | 
					@ -204,8 +204,8 @@ static gboolean handle_new_data(struct sr_dev_inst *sdi, int idx)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If we have any data left, move it to the beginning of our buffer. */
 | 
						/* If we have any data left, move it to the beginning of our buffer. */
 | 
				
			||||||
	for (i = 0; i < devc->buflen - offset; i++)
 | 
						if (offset < devc->buflen)
 | 
				
			||||||
		devc->buf[i] = devc->buf[offset + i];
 | 
							memmove(devc->buf, devc->buf + offset, devc->buflen - offset);
 | 
				
			||||||
	devc->buflen -= offset;
 | 
						devc->buflen -= offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -243,7 +243,7 @@ static int receive_data(int fd, int revents, int idx, void *cb_data)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->sw_limits))
 | 
						if (sr_sw_limits_check(&devc->sw_limits))
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,6 @@ extern SR_PRIV const struct center_dev_info center_devs[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SERIAL_BUFSIZE 256
 | 
					#define SERIAL_BUFSIZE 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	struct sr_sw_limits sw_limits;
 | 
						struct sr_sw_limits sw_limits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,14 +20,14 @@
 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t drvopts[] = {
 | 
					 | 
				
			||||||
	SR_CONF_LOGIC_ANALYZER,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const uint32_t scanopts[] = {
 | 
					static const uint32_t scanopts[] = {
 | 
				
			||||||
	SR_CONF_CONN,
 | 
						SR_CONF_CONN,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
 | 
						SR_CONF_LOGIC_ANALYZER,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
	SR_CONF_LIMIT_MSEC | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_MSEC | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_SET | SR_CONF_LIST,
 | 
						SR_CONF_LIMIT_SAMPLES | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
| 
						 | 
					@ -43,21 +43,15 @@ static const int32_t trigger_matches[] = {
 | 
				
			||||||
	SR_TRIGGER_FALLING,
 | 
						SR_TRIGGER_FALLING,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_stop(struct sr_dev_inst *sdi);
 | 
					static void clear_helper(struct dev_context *devc)
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void clear_helper(void *priv)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ftdi_free(devc->ftdic);
 | 
						ftdi_free(devc->ftdic);
 | 
				
			||||||
	g_free(devc->final_buf);
 | 
						g_free(devc->final_buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_clear(const struct sr_dev_driver *di)
 | 
					static int dev_clear(const struct sr_dev_driver *di)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return std_dev_clear(di, clear_helper);
 | 
						return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int add_device(int model, struct libusb_device_descriptor *des,
 | 
					static int add_device(int model, struct libusb_device_descriptor *des,
 | 
				
			||||||
| 
						 | 
					@ -71,7 +65,6 @@ static int add_device(int model, struct libusb_device_descriptor *des,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = SR_OK;
 | 
						ret = SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate memory for our private device context. */
 | 
					 | 
				
			||||||
	devc = g_malloc0(sizeof(struct dev_context));
 | 
						devc = g_malloc0(sizeof(struct dev_context));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set some sane defaults. */
 | 
						/* Set some sane defaults. */
 | 
				
			||||||
| 
						 | 
					@ -103,7 +96,6 @@ static int add_device(int model, struct libusb_device_descriptor *des,
 | 
				
			||||||
	/* We now know the device, set its max. samplerate as default. */
 | 
						/* We now know the device, set its max. samplerate as default. */
 | 
				
			||||||
	devc->cur_samplerate = devc->prof->max_samplerate;
 | 
						devc->cur_samplerate = devc->prof->max_samplerate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Register the device with libsigrok. */
 | 
					 | 
				
			||||||
	sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
						sdi = g_malloc0(sizeof(struct sr_dev_inst));
 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
						sdi->status = SR_ST_INACTIVE;
 | 
				
			||||||
	sdi->vendor = g_strdup("ChronoVu");
 | 
						sdi->vendor = g_strdup("ChronoVu");
 | 
				
			||||||
| 
						 | 
					@ -200,18 +192,17 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		libusb_close(hdl);
 | 
							libusb_close(hdl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!strcmp(product, "ChronoVu LA8")) {
 | 
							if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
 | 
				
			||||||
			model = 0;
 | 
					 | 
				
			||||||
		} else if (!strcmp(product, "ChronoVu LA16")) {
 | 
					 | 
				
			||||||
			model = 1;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			sr_spew("Unknown iProduct string '%s'.", product);
 | 
					 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
 | 
							if (!strcmp(product, "ChronoVu LA8"))
 | 
				
			||||||
 | 
								model = 0;
 | 
				
			||||||
 | 
							else if (!strcmp(product, "ChronoVu LA16"))
 | 
				
			||||||
 | 
								model = 1;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								continue; /* Unknown iProduct string, ignore. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sr_dbg("Found %s (%04x:%04x, %d.%d, %s).",
 | 
							sr_dbg("Found %s (%04x:%04x, %d.%d, %s).",
 | 
				
			||||||
		       product, des.idVendor, des.idProduct,
 | 
							       product, des.idVendor, des.idProduct,
 | 
				
			||||||
| 
						 | 
					@ -237,7 +228,6 @@ static int dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Allocate memory for the FTDI context and initialize it. */
 | 
					 | 
				
			||||||
	if (!(devc->ftdic = ftdi_new())) {
 | 
						if (!(devc->ftdic = ftdi_new())) {
 | 
				
			||||||
		sr_err("Failed to initialize libftdi.");
 | 
							sr_err("Failed to initialize libftdi.");
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
| 
						 | 
					@ -246,43 +236,33 @@ static int dev_open(struct sr_dev_inst *sdi)
 | 
				
			||||||
	sr_dbg("Opening %s device (%04x:%04x).", devc->prof->modelname,
 | 
						sr_dbg("Opening %s device (%04x:%04x).", devc->prof->modelname,
 | 
				
			||||||
	       devc->usb_vid, devc->usb_pid);
 | 
						       devc->usb_vid, devc->usb_pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Open the device. */
 | 
					 | 
				
			||||||
	if ((ret = ftdi_usb_open_desc(devc->ftdic, devc->usb_vid,
 | 
						if ((ret = ftdi_usb_open_desc(devc->ftdic, devc->usb_vid,
 | 
				
			||||||
			devc->usb_pid, devc->prof->iproduct, NULL)) < 0) {
 | 
								devc->usb_pid, devc->prof->iproduct, NULL)) < 0) {
 | 
				
			||||||
		sr_err("Failed to open FTDI device (%d): %s.",
 | 
							sr_err("Failed to open FTDI device (%d): %s.",
 | 
				
			||||||
		       ret, ftdi_get_error_string(devc->ftdic));
 | 
							       ret, ftdi_get_error_string(devc->ftdic));
 | 
				
			||||||
		goto err_ftdi_free;
 | 
							goto err_ftdi_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sr_dbg("Device opened successfully.");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Purge RX/TX buffers in the FTDI chip. */
 | 
						if ((ret = ftdi_tcioflush(devc->ftdic)) < 0) {
 | 
				
			||||||
	if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) {
 | 
					 | 
				
			||||||
		sr_err("Failed to purge FTDI buffers (%d): %s.",
 | 
							sr_err("Failed to purge FTDI buffers (%d): %s.",
 | 
				
			||||||
		       ret, ftdi_get_error_string(devc->ftdic));
 | 
							       ret, ftdi_get_error_string(devc->ftdic));
 | 
				
			||||||
		goto err_ftdi_free;
 | 
							goto err_ftdi_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sr_dbg("FTDI buffers purged successfully.");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Enable flow control in the FTDI chip. */
 | 
					 | 
				
			||||||
	if ((ret = ftdi_setflowctrl(devc->ftdic, SIO_RTS_CTS_HS)) < 0) {
 | 
						if ((ret = ftdi_setflowctrl(devc->ftdic, SIO_RTS_CTS_HS)) < 0) {
 | 
				
			||||||
		sr_err("Failed to enable FTDI flow control (%d): %s.",
 | 
							sr_err("Failed to enable FTDI flow control (%d): %s.",
 | 
				
			||||||
		       ret, ftdi_get_error_string(devc->ftdic));
 | 
							       ret, ftdi_get_error_string(devc->ftdic));
 | 
				
			||||||
		goto err_ftdi_free;
 | 
							goto err_ftdi_free;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sr_dbg("FTDI flow control enabled successfully.");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Wait 100ms. */
 | 
					 | 
				
			||||||
	g_usleep(100 * 1000);
 | 
						g_usleep(100 * 1000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdi->status = SR_ST_ACTIVE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ret == SR_OK)
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err_ftdi_free:
 | 
					err_ftdi_free:
 | 
				
			||||||
	ftdi_free(devc->ftdic); /* Close device (if open), free FTDI context. */
 | 
						ftdi_free(devc->ftdic); /* Close device (if open), free FTDI context. */
 | 
				
			||||||
	devc->ftdic = NULL;
 | 
						devc->ftdic = NULL;
 | 
				
			||||||
	return ret;
 | 
						return SR_ERR;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_close(struct sr_dev_inst *sdi)
 | 
					static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -290,25 +270,23 @@ static int dev_close(struct sr_dev_inst *sdi)
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_OK;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (devc->ftdic && (ret = ftdi_usb_close(devc->ftdic)) < 0)
 | 
						if (!devc->ftdic)
 | 
				
			||||||
 | 
							return SR_ERR_BUG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((ret = ftdi_usb_close(devc->ftdic)) < 0)
 | 
				
			||||||
		sr_err("Failed to close FTDI device (%d): %s.",
 | 
							sr_err("Failed to close FTDI device (%d): %s.",
 | 
				
			||||||
		       ret, ftdi_get_error_string(devc->ftdic));
 | 
							       ret, ftdi_get_error_string(devc->ftdic));
 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return (ret == 0) ? SR_OK : SR_ERR;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_get(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_usb_dev_inst *usb;
 | 
						struct sr_usb_dev_inst *usb;
 | 
				
			||||||
	char str[128];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,8 +294,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	case SR_CONF_CONN:
 | 
						case SR_CONF_CONN:
 | 
				
			||||||
		if (!sdi || !(usb = sdi->conn))
 | 
							if (!sdi || !(usb = sdi->conn))
 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		snprintf(str, 128, "%d.%d", usb->bus, usb->address);
 | 
							*data = g_variant_new_printf("%d.%d", usb->bus, usb->address);
 | 
				
			||||||
		*data = g_variant_new_string(str);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		if (!sdi)
 | 
							if (!sdi)
 | 
				
			||||||
| 
						 | 
					@ -332,16 +309,13 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
| 
						 | 
					@ -350,13 +324,9 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
			return SR_ERR;
 | 
								return SR_ERR;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_MSEC:
 | 
						case SR_CONF_LIMIT_MSEC:
 | 
				
			||||||
		if (g_variant_get_uint64(data) == 0)
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
					 | 
				
			||||||
		devc->limit_msec = g_variant_get_uint64(data);
 | 
							devc->limit_msec = g_variant_get_uint64(data);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		if (g_variant_get_uint64(data) == 0)
 | 
					 | 
				
			||||||
			return SR_ERR_ARG;
 | 
					 | 
				
			||||||
		devc->limit_samples = g_variant_get_uint64(data);
 | 
							devc->limit_samples = g_variant_get_uint64(data);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
| 
						 | 
					@ -366,57 +336,30 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GVariant *gvar, *grange[2];
 | 
					 | 
				
			||||||
	GVariantBuilder gvb;
 | 
					 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						devc = (sdi) ? sdi->priv : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
		if (!sdi)
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
					devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_SAMPLERATE:
 | 
						case SR_CONF_SAMPLERATE:
 | 
				
			||||||
		if (!sdi)
 | 
					 | 
				
			||||||
			return SR_ERR_BUG;
 | 
					 | 
				
			||||||
		devc = sdi->priv;
 | 
					 | 
				
			||||||
		cv_fill_samplerates_if_needed(sdi);
 | 
							cv_fill_samplerates_if_needed(sdi);
 | 
				
			||||||
		g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
 | 
							*data = std_gvar_samplerates(ARRAY_AND_SIZE(devc->samplerates));
 | 
				
			||||||
		gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
 | 
					 | 
				
			||||||
				devc->samplerates,
 | 
					 | 
				
			||||||
				ARRAY_SIZE(devc->samplerates),
 | 
					 | 
				
			||||||
				sizeof(uint64_t));
 | 
					 | 
				
			||||||
		g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
 | 
					 | 
				
			||||||
		*data = g_variant_builder_end(&gvb);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_LIMIT_SAMPLES:
 | 
						case SR_CONF_LIMIT_SAMPLES:
 | 
				
			||||||
		if (!sdi || !sdi->priv || !(devc = sdi->priv) || !devc->prof)
 | 
							if (!devc || !devc->prof)
 | 
				
			||||||
			return SR_ERR_BUG;
 | 
								return SR_ERR_BUG;
 | 
				
			||||||
		grange[0] = g_variant_new_uint64(0);
 | 
							*data = std_gvar_tuple_u64(0, (devc->prof->model == CHRONOVU_LA8) ? MAX_NUM_SAMPLES : MAX_NUM_SAMPLES / 2);
 | 
				
			||||||
		if (devc->prof->model == CHRONOVU_LA8)
 | 
					 | 
				
			||||||
			grange[1] = g_variant_new_uint64(MAX_NUM_SAMPLES);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			grange[1] = g_variant_new_uint64(MAX_NUM_SAMPLES / 2);
 | 
					 | 
				
			||||||
		*data = g_variant_new_tuple(grange, 2);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SR_CONF_TRIGGER_MATCH:
 | 
						case SR_CONF_TRIGGER_MATCH:
 | 
				
			||||||
		if (!sdi || !sdi->priv || !(devc = sdi->priv) || !devc->prof)
 | 
							if (!devc || !devc->prof)
 | 
				
			||||||
			return SR_ERR_BUG;
 | 
								return SR_ERR_BUG;
 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
 | 
							*data = std_gvar_array_i32(trigger_matches, devc->prof->num_trigger_matches);
 | 
				
			||||||
				trigger_matches, devc->prof->num_trigger_matches,
 | 
					 | 
				
			||||||
				sizeof(int32_t));
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
| 
						 | 
					@ -452,7 +395,7 @@ static int receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	/* Get one block of data. */
 | 
						/* Get one block of data. */
 | 
				
			||||||
	if ((ret = cv_read_block(devc)) < 0) {
 | 
						if ((ret = cv_read_block(devc)) < 0) {
 | 
				
			||||||
		sr_err("Failed to read data block: %d.", ret);
 | 
							sr_err("Failed to read data block: %d.", ret);
 | 
				
			||||||
		dev_acquisition_stop(sdi);
 | 
							sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
		return FALSE;
 | 
							return FALSE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -475,7 +418,7 @@ static int receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
	for (i = 0; i < NUM_BLOCKS; i++)
 | 
						for (i = 0; i < NUM_BLOCKS; i++)
 | 
				
			||||||
		cv_send_block_to_session_bus(sdi, i);
 | 
							cv_send_block_to_session_bus(sdi, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_acquisition_stop(sdi);
 | 
						sr_dev_acquisition_stop(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -486,9 +429,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	uint8_t buf[8];
 | 
						uint8_t buf[8];
 | 
				
			||||||
	int bytes_to_write, bytes_written;
 | 
						int bytes_to_write, bytes_written;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!devc->ftdic) {
 | 
						if (!devc->ftdic) {
 | 
				
			||||||
| 
						 | 
					@ -534,8 +474,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
		return SR_ERR;
 | 
							return SR_ERR;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_dbg("Hardware acquisition started successfully.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Time when we should be done (for detecting trigger timeouts). */
 | 
						/* Time when we should be done (for detecting trigger timeouts). */
 | 
				
			||||||
| 
						 | 
					@ -552,7 +490,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sr_dbg("Stopping acquisition.");
 | 
					 | 
				
			||||||
	sr_session_source_remove(sdi->session, -1);
 | 
						sr_session_source_remove(sdi->session, -1);
 | 
				
			||||||
	std_session_send_df_end(sdi);
 | 
						std_session_send_df_end(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,7 +202,7 @@ static int close_usb_reset_sequencer(struct dev_context *devc)
 | 
				
			||||||
		sr_dbg("Purging buffers, resetting+closing FTDI device.");
 | 
							sr_dbg("Purging buffers, resetting+closing FTDI device.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Log errors, but ignore them (i.e., don't abort). */
 | 
							/* Log errors, but ignore them (i.e., don't abort). */
 | 
				
			||||||
		if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0)
 | 
							if ((ret = ftdi_tcioflush(devc->ftdic)) < 0)
 | 
				
			||||||
			sr_err("Failed to purge FTDI buffers (%d): %s.",
 | 
								sr_err("Failed to purge FTDI buffers (%d): %s.",
 | 
				
			||||||
			       ret, ftdi_get_error_string(devc->ftdic));
 | 
								       ret, ftdi_get_error_string(devc->ftdic));
 | 
				
			||||||
		if ((ret = ftdi_usb_reset(devc->ftdic)) < 0)
 | 
							if ((ret = ftdi_usb_reset(devc->ftdic)) < 0)
 | 
				
			||||||
| 
						 | 
					@ -300,6 +300,11 @@ SR_PRIV int cv_convert_trigger(const struct sr_dev_inst *sdi)
 | 
				
			||||||
					|| match->match == SR_TRIGGER_RISING)
 | 
										|| match->match == SR_TRIGGER_RISING)
 | 
				
			||||||
				devc->trigger_pattern |= channel_bit;
 | 
									devc->trigger_pattern |= channel_bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* LA8 and LA16 support state triggering. */
 | 
				
			||||||
 | 
								if (match->match == SR_TRIGGER_ONE
 | 
				
			||||||
 | 
										|| match->match == SR_TRIGGER_ZERO)
 | 
				
			||||||
 | 
									devc->trigger_mask |= channel_bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* LA16 (but not LA8) supports edge triggering. */
 | 
								/* LA16 (but not LA8) supports edge triggering. */
 | 
				
			||||||
			if ((devc->prof->model == CHRONOVU_LA16)) {
 | 
								if ((devc->prof->model == CHRONOVU_LA16)) {
 | 
				
			||||||
				if (match->match == SR_TRIGGER_RISING
 | 
									if (match->match == SR_TRIGGER_RISING
 | 
				
			||||||
| 
						 | 
					@ -489,9 +494,7 @@ SR_PRIV void cv_send_block_to_session_bus(const struct sr_dev_inst *sdi, int blo
 | 
				
			||||||
	/* Send the SR_DF_TRIGGER packet to the session bus. */
 | 
						/* Send the SR_DF_TRIGGER packet to the session bus. */
 | 
				
			||||||
	sr_spew("Sending SR_DF_TRIGGER packet, sample = %d.",
 | 
						sr_spew("Sending SR_DF_TRIGGER packet, sample = %d.",
 | 
				
			||||||
		(block * BS) + trigger_point);
 | 
							(block * BS) + trigger_point);
 | 
				
			||||||
	packet.type = SR_DF_TRIGGER;
 | 
						std_session_send_df_trigger(sdi);
 | 
				
			||||||
	packet.payload = NULL;
 | 
					 | 
				
			||||||
	sr_session_send(sdi, &packet);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If at least one sample is located after the trigger... */
 | 
						/* If at least one sample is located after the trigger... */
 | 
				
			||||||
	if (trigger_point < (BS - 1)) {
 | 
						if (trigger_point < (BS - 1)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@
 | 
				
			||||||
#include <libsigrok/libsigrok.h>
 | 
					#include <libsigrok/libsigrok.h>
 | 
				
			||||||
#include "libsigrok-internal.h"
 | 
					#include "libsigrok-internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOG_PREFIX "la8/la16"
 | 
					#define LOG_PREFIX "chronovu-la"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SDRAM_SIZE			(8 * 1024 * 1024)
 | 
					#define SDRAM_SIZE			(8 * 1024 * 1024)
 | 
				
			||||||
#define MAX_NUM_SAMPLES			SDRAM_SIZE
 | 
					#define MAX_NUM_SAMPLES			SDRAM_SIZE
 | 
				
			||||||
| 
						 | 
					@ -44,28 +44,18 @@ enum {
 | 
				
			||||||
struct cv_profile {
 | 
					struct cv_profile {
 | 
				
			||||||
	int model;
 | 
						int model;
 | 
				
			||||||
	const char *modelname;
 | 
						const char *modelname;
 | 
				
			||||||
	const char *iproduct; /* USB iProduct string */
 | 
						const char *iproduct;
 | 
				
			||||||
	unsigned int num_channels;
 | 
						unsigned int num_channels;
 | 
				
			||||||
	uint64_t max_samplerate;
 | 
						uint64_t max_samplerate;
 | 
				
			||||||
	const int num_trigger_matches;
 | 
						const int num_trigger_matches;
 | 
				
			||||||
	float trigger_constant;
 | 
						float trigger_constant;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	/** Device profile struct for this device. */
 | 
					 | 
				
			||||||
	const struct cv_profile *prof;
 | 
						const struct cv_profile *prof;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** FTDI device context (used by libftdi). */
 | 
					 | 
				
			||||||
	struct ftdi_context *ftdic;
 | 
						struct ftdi_context *ftdic;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** The currently configured samplerate of the device. */
 | 
					 | 
				
			||||||
	uint64_t cur_samplerate;
 | 
						uint64_t cur_samplerate;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** The current sampling limit (in ms). */
 | 
					 | 
				
			||||||
	uint64_t limit_msec;
 | 
						uint64_t limit_msec;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/** The current sampling limit (in number of samples). */
 | 
					 | 
				
			||||||
	uint64_t limit_samples;
 | 
						uint64_t limit_samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -124,7 +114,6 @@ struct dev_context {
 | 
				
			||||||
	uint64_t samplerates[255];
 | 
						uint64_t samplerates[255];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* protocol.c */
 | 
					 | 
				
			||||||
extern SR_PRIV const char *cv_channel_names[];
 | 
					extern SR_PRIV const char *cv_channel_names[];
 | 
				
			||||||
extern const struct cv_profile cv_profiles[];
 | 
					extern const struct cv_profile cv_profiles[];
 | 
				
			||||||
SR_PRIV void cv_fill_samplerates_if_needed(const struct sr_dev_inst *sdi);
 | 
					SR_PRIV void cv_fill_samplerates_if_needed(const struct sr_dev_inst *sdi);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,8 +35,11 @@ static const uint32_t scanopts[] = {
 | 
				
			||||||
	SR_CONF_SERIALCOMM,
 | 
						SR_CONF_SERIALCOMM,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
	SR_CONF_SOUNDLEVELMETER,
 | 
						SR_CONF_SOUNDLEVELMETER,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
	SR_CONF_CONTINUOUS,
 | 
						SR_CONF_CONTINUOUS,
 | 
				
			||||||
	SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
 | 
				
			||||||
	SR_CONF_LIMIT_MSEC | SR_CONF_SET,
 | 
						SR_CONF_LIMIT_MSEC | SR_CONF_SET,
 | 
				
			||||||
| 
						 | 
					@ -81,41 +84,22 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
						return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dev_context *devc;
 | 
						struct dev_context *devc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	devc = sdi->priv;
 | 
						devc = sdi->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
						return sr_sw_limits_config_set(&devc->limits, key, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	(void)sdi;
 | 
						return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
| 
						 | 
					@ -123,13 +107,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	struct dev_context *devc = sdi->priv;
 | 
						struct dev_context *devc = sdi->priv;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sr_sw_limits_acquisition_start(&devc->limits);
 | 
						sr_sw_limits_acquisition_start(&devc->limits);
 | 
				
			||||||
	std_session_send_df_header(sdi);
 | 
						std_session_send_df_header(sdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Poll every 150ms, or whenever some data comes in. */
 | 
					 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	serial_source_add(sdi->session, serial, G_IO_IN, 150,
 | 
						serial_source_add(sdi->session, serial, G_IO_IN, 150,
 | 
				
			||||||
			colead_slm_receive_data, (void *)sdi);
 | 
								colead_slm_receive_data, (void *)sdi);
 | 
				
			||||||
| 
						 | 
					@ -145,7 +125,7 @@ static struct sr_dev_driver colead_slm_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = NULL,
 | 
						.config_get = NULL,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +177,7 @@ static void process_packet(const struct sr_dev_inst *sdi)
 | 
				
			||||||
	sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
						sr_sw_limits_update_samples_read(&devc->limits, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sr_sw_limits_check(&devc->limits))
 | 
						if (sr_sw_limits_check(&devc->limits))
 | 
				
			||||||
		sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
							sr_dev_acquisition_stop((struct sr_dev_inst *)sdi);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SR_PRIV int colead_slm_receive_data(int fd, int revents, void *cb_data)
 | 
					SR_PRIV int colead_slm_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
| 
						 | 
					@ -202,7 +202,7 @@ SR_PRIV int colead_slm_receive_data(int fd, int revents, void *cb_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial = sdi->conn;
 | 
						serial = sdi->conn;
 | 
				
			||||||
	if (devc->state == IDLE) {
 | 
						if (devc->state == IDLE) {
 | 
				
			||||||
		if (serial_read_nonblocking(serial, buf, 128) != 1 || buf[0] != 0x10)
 | 
							if (serial_read_nonblocking(serial, buf, sizeof(buf)) != 1 || buf[0] != 0x10)
 | 
				
			||||||
			/* Nothing there, or caught the tail end of a previous packet,
 | 
								/* Nothing there, or caught the tail end of a previous packet,
 | 
				
			||||||
			 * or some garbage. Unless it's a single "data ready" byte,
 | 
								 * or some garbage. Unless it's a single "data ready" byte,
 | 
				
			||||||
			 * we don't want it. */
 | 
								 * we don't want it. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,6 @@ enum {
 | 
				
			||||||
	COMMAND_SENT,
 | 
						COMMAND_SENT,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Private, per-device-instance driver context. */
 | 
					 | 
				
			||||||
struct dev_context {
 | 
					struct dev_context {
 | 
				
			||||||
	struct sr_sw_limits limits;
 | 
						struct sr_sw_limits limits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,14 +17,6 @@
 | 
				
			||||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @file
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * <em>Conrad DIGI 35 CPU</em> power supply driver
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @internal
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <config.h>
 | 
					#include <config.h>
 | 
				
			||||||
#include "protocol.h"
 | 
					#include "protocol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,15 +27,19 @@ static const uint32_t scanopts[] = {
 | 
				
			||||||
	SR_CONF_SERIALCOMM,
 | 
						SR_CONF_SERIALCOMM,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const uint32_t devopts[] = {
 | 
					static const uint32_t drvopts[] = {
 | 
				
			||||||
	SR_CONF_POWER_SUPPLY,
 | 
						SR_CONF_POWER_SUPPLY,
 | 
				
			||||||
	SR_CONF_VOLTAGE | SR_CONF_SET,
 | 
					};
 | 
				
			||||||
	SR_CONF_CURRENT | SR_CONF_SET,
 | 
					
 | 
				
			||||||
 | 
					static const uint32_t devopts[] = {
 | 
				
			||||||
 | 
						SR_CONF_VOLTAGE_TARGET | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
 | 
						SR_CONF_CURRENT_LIMIT | SR_CONF_SET | SR_CONF_LIST,
 | 
				
			||||||
	SR_CONF_OVER_CURRENT_PROTECTION_ENABLED | SR_CONF_SET,
 | 
						SR_CONF_OVER_CURRENT_PROTECTION_ENABLED | SR_CONF_SET,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
					static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dev_context *devc;
 | 
				
			||||||
	struct sr_dev_inst *sdi;
 | 
						struct sr_dev_inst *sdi;
 | 
				
			||||||
	struct sr_config *src;
 | 
						struct sr_config *src;
 | 
				
			||||||
	struct sr_serial_dev_inst *serial;
 | 
						struct sr_serial_dev_inst *serial;
 | 
				
			||||||
| 
						 | 
					@ -79,7 +75,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
						if (serial_open(serial, SERIAL_RDWR) != SR_OK)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serial_flush(serial);
 | 
					 | 
				
			||||||
	serial_close(serial);
 | 
						serial_close(serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sr_spew("Conrad DIGI 35 CPU assumed at %s.", conn);
 | 
						sr_spew("Conrad DIGI 35 CPU assumed at %s.", conn);
 | 
				
			||||||
| 
						 | 
					@ -88,91 +83,65 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 | 
				
			||||||
	sdi->status = SR_ST_INACTIVE;
 | 
						sdi->status = SR_ST_INACTIVE;
 | 
				
			||||||
	sdi->vendor = g_strdup("Conrad");
 | 
						sdi->vendor = g_strdup("Conrad");
 | 
				
			||||||
	sdi->model = g_strdup("DIGI 35 CPU");
 | 
						sdi->model = g_strdup("DIGI 35 CPU");
 | 
				
			||||||
 | 
						devc = g_malloc0(sizeof(struct dev_context));
 | 
				
			||||||
 | 
						sr_sw_limits_init(&devc->limits);
 | 
				
			||||||
 | 
						sdi->inst_type = SR_INST_SERIAL;
 | 
				
			||||||
	sdi->conn = serial;
 | 
						sdi->conn = serial;
 | 
				
			||||||
	sdi->priv = NULL;
 | 
						sdi->priv = devc;
 | 
				
			||||||
	sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "CH1");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
						return std_scan_complete(di, g_slist_append(NULL, sdi));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
 | 
					static int config_set(uint32_t key, GVariant *data,
 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	double dblval;
 | 
						double dblval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(void)cg;
 | 
						(void)cg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (key) {
 | 
						switch (key) {
 | 
				
			||||||
	case SR_CONF_VOLTAGE:
 | 
						case SR_CONF_VOLTAGE_TARGET:
 | 
				
			||||||
		dblval = g_variant_get_double(data);
 | 
							dblval = g_variant_get_double(data);
 | 
				
			||||||
		if ((dblval < 0.0) || (dblval > 35.0)) {
 | 
							if ((dblval < 0.0) || (dblval > 35.0)) {
 | 
				
			||||||
			sr_err("Voltage out of range (0 - 35.0)!");
 | 
								sr_err("Voltage out of range (0 - 35.0)!");
 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ret = send_msg1(sdi, 'V', (int) (dblval * 10 + 0.5));
 | 
							return send_msg1(sdi, 'V', (int) (dblval * 10 + 0.5));
 | 
				
			||||||
		break;
 | 
						case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
	case SR_CONF_CURRENT:
 | 
					 | 
				
			||||||
		dblval = g_variant_get_double(data);
 | 
							dblval = g_variant_get_double(data);
 | 
				
			||||||
		if ((dblval < 0.01) || (dblval > 2.55)) {
 | 
							if ((dblval < 0.00) || (dblval > 2.55)) {
 | 
				
			||||||
			sr_err("Current out of range (0 - 2.55)!");
 | 
								sr_err("Current out of range (0 - 2.55)!");
 | 
				
			||||||
			return SR_ERR_ARG;
 | 
								return SR_ERR_ARG;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ret = send_msg1(sdi, 'C', (int) (dblval * 100 + 0.5));
 | 
							return send_msg1(sdi, 'C', (int) (dblval * 100 + 0.5));
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
 | 
						case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
 | 
				
			||||||
		if (g_variant_get_boolean(data))
 | 
							if (g_variant_get_boolean(data))
 | 
				
			||||||
			ret = send_msg1(sdi, 'V', 900);
 | 
								return send_msg1(sdi, 'V', 900);
 | 
				
			||||||
		else /* Constant current mode */
 | 
							else /* Constant current mode */
 | 
				
			||||||
			ret = send_msg1(sdi, 'V', 901);
 | 
								return send_msg1(sdi, 'V', 901);
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		ret = SR_ERR_NA;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
 | 
					 | 
				
			||||||
		const struct sr_channel_group *cg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	(void)sdi;
 | 
					 | 
				
			||||||
	(void)cg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = SR_OK;
 | 
					 | 
				
			||||||
	switch (key) {
 | 
					 | 
				
			||||||
	case SR_CONF_SCAN_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SR_CONF_DEVICE_OPTIONS:
 | 
					 | 
				
			||||||
		*data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
 | 
					 | 
				
			||||||
				devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return SR_ERR_NA;
 | 
							return SR_ERR_NA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dev_acquisition_start(const struct sr_dev_inst *sdi)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
					 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dev_acquisition_stop(struct sr_dev_inst *sdi)
 | 
					static int config_list(uint32_t key, GVariant **data,
 | 
				
			||||||
 | 
						const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (sdi->status != SR_ST_ACTIVE)
 | 
						switch (key) {
 | 
				
			||||||
		return SR_ERR_DEV_CLOSED;
 | 
						case SR_CONF_SCAN_OPTIONS:
 | 
				
			||||||
 | 
						case SR_CONF_DEVICE_OPTIONS:
 | 
				
			||||||
 | 
							return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 | 
				
			||||||
 | 
						case SR_CONF_VOLTAGE_TARGET:
 | 
				
			||||||
 | 
							*data = std_gvar_min_max_step(0.0, 35.0, 0.1);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SR_CONF_CURRENT_LIMIT:
 | 
				
			||||||
 | 
							*data = std_gvar_min_max_step(0.0, 2.55, 0.01);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return SR_ERR_NA;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return SR_OK;
 | 
						return SR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -185,14 +154,14 @@ static struct sr_dev_driver conrad_digi_35_cpu_driver_info = {
 | 
				
			||||||
	.cleanup = std_cleanup,
 | 
						.cleanup = std_cleanup,
 | 
				
			||||||
	.scan = scan,
 | 
						.scan = scan,
 | 
				
			||||||
	.dev_list = std_dev_list,
 | 
						.dev_list = std_dev_list,
 | 
				
			||||||
	.dev_clear = NULL,
 | 
						.dev_clear = std_dev_clear,
 | 
				
			||||||
	.config_get = NULL,
 | 
						.config_get = NULL,
 | 
				
			||||||
	.config_set = config_set,
 | 
						.config_set = config_set,
 | 
				
			||||||
	.config_list = config_list,
 | 
						.config_list = config_list,
 | 
				
			||||||
	.dev_open = std_serial_dev_open,
 | 
						.dev_open = std_serial_dev_open,
 | 
				
			||||||
	.dev_close = std_serial_dev_close,
 | 
						.dev_close = std_serial_dev_close,
 | 
				
			||||||
	.dev_acquisition_start = dev_acquisition_start,
 | 
						.dev_acquisition_start = std_dummy_dev_acquisition_start,
 | 
				
			||||||
	.dev_acquisition_stop = dev_acquisition_stop,
 | 
						.dev_acquisition_stop = std_dummy_dev_acquisition_stop,
 | 
				
			||||||
	.context = NULL,
 | 
						.context = NULL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
SR_REGISTER_DEV_DRIVER(conrad_digi_35_cpu_driver_info);
 | 
					SR_REGISTER_DEV_DRIVER(conrad_digi_35_cpu_driver_info);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue