Class: UVC::UVCDevice

Inherits:
Object
  • Object
show all
Defined in:
lib/uvc.rb

Defined Under Namespace

Classes: Info, UVCError

Constant Summary collapse

KNOWN_CONTROLS =

mapping size: 1 | unsigned number => C size: 1 | signed number => c size: 2 | unsigned number => v size: 2 | signed number => s< size: 4 | unsigned number => V size: 4 | signed number => l<

[
	{
		selector: Controls::CT_SCANNING_MODE_CONTROL,
		length: 1,
		encode: lambda {|x| [x ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1 },
	},
	{
		selector: Controls::CT_AE_MODE_CONTROL,
		length: 1,
		encode: lambda {|mode| [mode].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] },
	},
	{
		selector: Controls::CT_AE_PRIORITY_CONTROL,
		length: 1,
		encode: lambda {|bAutoExposurePriority| [bAutoExposurePriority].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] },
	},
	{
		selector: Controls::CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
		length: 4,
		encode: lambda {|dwExposureTimeAbsolute| [dwExposureTimeAbsolute].pack("V")},
		decode: lambda {|x| x.unpack("V")[0] },
	},
	{
		selector: Controls::CT_EXPOSURE_TIME_RELATIVE_CONTROL,
		length: 1,
		encode: lambda {|bExposureTimeRelative| [bExposureTimeRelative].pack("c")},
		decode: lambda {|x| x.unpack("c")[0] },
	},
	{
		selector: Controls::CT_FOCUS_ABSOLUTE_CONTROL,
		length: 2,
		encode: lambda {|wFocusAbsolute| [wFocusAbsolute].pack("v")},
		decode: lambda {|x| x.unpack("v")[0] },
	},
	{
		selector: Controls::CT_FOCUS_RELATIVE_CONTROL,
		length: 2,
		encode: lambda {|(bFocusRelative,bSpeed)| [wFocusAbsolute].pack("cC")},
		decode: lambda {|x| x.unpack("cC") },
	},
	{
		selector: Controls::CT_FOCUS_SIMPLE_CONTROL,
		length: 1,
		encode: lambda {|bFocus| [wFocusAbsolute].pack("C")},
		decode: lambda {|x| x.unpack("C") },
	},
	{
		selector: Controls::CT_FOCUS_AUTO_CONTROL,
		length: 1,
		encode: lambda {|bFocusAuto| [bFocusAuto ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1},
	},
	{
		selector: Controls::CT_IRIS_ABSOLUTE_CONTROL,
		length: 2,
		encode: lambda {|wIrisAbsolute| [wIrisAbsolute].pack("v")},
		decode: lambda {|x| x.unpack("v")[0] },
	},
	{
		selector: Controls::CT_IRIS_RELATIVE_CONTROL,
		length: 1,
		encode: lambda {|bIrisRelative| [bIrisRelative].pack("c")},
		decode: lambda {|x| x.unpack("c")[0] },
	},
	{
		selector: Controls::CT_ZOOM_ABSOLUTE_CONTROL,
		length: 2,
		encode: lambda {|wObjectiveFocalLength| [wObjectiveFocalLength].pack("v")},
		decode: lambda {|x| x.unpack("v")[0] },
	},
	{
		selector: Controls::CT_ZOOM_RELATIVE_CONTROL,
		length: 3,
		encode: lambda {|(bZoom, bDigitalZoom, bSpeed)| [bZoom, bDigitalZoom ? 1 : 0, bSpeed].pack("cCC")},
		decode: lambda {|x| x.unpack("cCC").tap {|a| a[1] = a[1] == 1 } },
	},
	{
		selector: Controls::CT_PANTILT_ABSOLUTE_CONTROL,
		length: 8,
		encode: lambda {|(dwPanAbsolute, dwTiltAbsolute)| [dwPanAbsolute, dwTiltAbsolute].pack("l<l<")},
		decode: lambda {|x| x.unpack("l<l<") },
	},
	{
		selector: Controls::CT_PANTILT_RELATIVE_CONTROL,
		length: 4,
		encode: lambda {|(bPanRelative, bPanSpeed, bTiltRelative, bTiltSpeed)| [bPanRelative, bPanSpeed, bTiltRelative, bTiltSpeed].pack("cCcC")},
		decode: lambda {|x| x.unpack("cCcC") },
	},
	{
		selector: Controls::CT_ROLL_ABSOLUTE_CONTROL,
		length: 2,
		encode: lambda {|wRollAbsolute| [wRollAbsolute].pack("s<")},
		decode: lambda {|x| x.unpack("s<")[0] },
	},
	{
		selector: Controls::CT_ROLL_RELATIVE_CONTROL,
		length: 2,
		encode: lambda {|(bRollRelative, bSpeed)| [bRollRelative, bSpeed].pack("cC")},
		decode: lambda {|x| x.unpack("cC") },
	},
	{
		selector: Controls::CT_PRIVACY_CONTROL,
		length: 1,
		encode: lambda {|bPrivacy| [bPrivacy ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1 },
	},
	{
		selector: Controls::CT_WINDOW_CONTROL,
		length: 12,
		encode: lambda {|(wWindow_Top, wWindow_Left, wWindow_Bottom, wWindow_Right, wNumSteps, bmNumStepsUnits)| [wWindow_Top, wWindow_Left, wWindow_Bottom, wWindow_Right, wNumSteps, bmNumStepsUnits].pack("vvvvvv")},
		decode: lambda {|x| x.unpack("vvvvvv") },
	},
	{
		selector: Controls::CT_REGION_OF_INTEREST_CONTROL,
		length: 10,
		encode: lambda {|(wROI_Top, wROI_Left, wROI_Bottom, wROI_Right, bmAutoControls)| [wROI_Top, wROI_Left, wROI_Bottom, wROI_Right, bmAutoControls].pack("vvvvv")},
		decode: lambda {|x| x.unpack("vvvvv") },
	},

	{
		selector: Controls::SU_INPUT_SELECT_CONTROL,
		length: 1,
		encode: lambda {|bSelector| [bSelector].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] },
	},

	{
		selector: Controls::PU_BACKLIGHT_COMPENSATION_CONTROL,
		length: 2,
		encode: lambda {|wBacklightCompensation| [wBacklightCompensation].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_BRIGHTNESS_CONTROL,
		length: 2,
		encode: lambda {|wBrightness| [wBrightness].pack("s<")},
		decode: lambda {|x| x.unpack("s<")[0]},
	},
	{
		selector: Controls::PU_CONTRAST_CONTROL,
		length: 2,
		encode: lambda {|wContrast| [wContrast].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_CONTRAST_AUTO_CONTROL,
		length: 1,
		encode: lambda {|bContrastAuto| [bContrastAuto ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1},
	},
	{
		selector: Controls::PU_GAIN_CONTROL,
		length: 2,
		encode: lambda {|wGain| [wGain].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_POWER_LINE_FREQUENCY_CONTROL,
		length: 1,
		encode: lambda {|bPowerLineFrequency| [bPowerLineFrequency].pack("C")},
		decode: lambda {|x| x.unpack("C")[0]},
	},
	{
		selector: Controls::PU_HUE_CONTROL,
		length: 2,
		encode: lambda {|wHue| [wHue].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_HUE_AUTO_CONTROL,
		length: 1,
		encode: lambda {|bHueAuto| [bHueAuto ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1},
	},
	{
		selector: Controls::PU_SATURATION_CONTROL,
		length: 2,
		encode: lambda {|wSaturation| [wSaturation].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_SHARPNESS_CONTROL,
		length: 2,
		encode: lambda {|wSharpness| [wSharpness].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_GAMMA_CONTROL,
		length: 2,
		encode: lambda {|wGamma| [wGamma].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
		length: 2,
		encode: lambda {|wWhiteBalanceTemperature| [wWhiteBalanceTemperature].pack("v")},
		decode: lambda {|x| x.unpack("v")[0]},
	},
	{
		selector: Controls::PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
		length: 1,
		encode: lambda {|bWhiteBalanceTemperatureAuto| [bWhiteBalanceTemperatureAuto ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1},
	},
	{
		selector: Controls::PU_WHITE_BALANCE_COMPONENT_CONTROL,
		length: 4,
		encode: lambda {|(wWhiteBalanceBlue, wWhiteBalanceRed)| [wWhiteBalanceBlue, wWhiteBalanceRed].pack("vv")},
		decode: lambda {|x| x.unpack("vv") },
	},
	{
		selector: Controls::PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
		length: 1,
		encode: lambda {|bWhiteBalanceComponentAuto| [bWhiteBalanceComponentAuto ? 1 : 0].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] == 1},
	},
	{
		selector: Controls::PU_DIGITAL_MULTIPLIER_CONTROL,
		length: 2,
		encode: lambda {|wMultiplierStep| [wMultiplierStep].pack("v")},
		decode: lambda {|x| x.unpack("v")[0] },
	},
	{
		selector: Controls::PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
		length: 2,
		encode: lambda {|wMultiplierLimit| [wMultiplierLimit].pack("v")},
		decode: lambda {|x| x.unpack("v")[0] },
	},
	{
		selector: Controls::PU_ANALOG_VIDEO_STANDARD_CONTROL,
		length: 1,
		encode: lambda {|bVideoStandard| [bVideoStandard].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] },
	},
	{
		selector: Controls::PU_ANALOG_LOCK_STATUS_CONTROL,
		length: 1,
		encode: lambda {|bStatus| [bStatus].pack("C")},
		decode: lambda {|x| x.unpack("C")[0] },
	},
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(setting) ⇒ UVCDevice

Returns a new instance of UVCDevice.



667
668
669
670
# File 'lib/uvc.rb', line 667

def initialize(setting)
	@setting = setting
	@descriptors = ClassSpecificVCInterfaceDescriptor.parse_array(setting.extra)
end

Instance Attribute Details

#descriptorsObject (readonly)

Returns the value of attribute descriptors.



665
666
667
# File 'lib/uvc.rb', line 665

def descriptors
  @descriptors
end

Class Method Details

.devicesObject



653
654
655
# File 'lib/uvc.rb', line 653

def self.devices
	libusb.devices(bClass: 0xef, bSubClass: 0x02, bProtocol: 1)
end

.libusbObject



649
650
651
# File 'lib/uvc.rb', line 649

def self.libusb
	@@libusb ||= LIBUSB::Context.new
end

.video_control_interface_settings_of(device) ⇒ Object



657
658
659
660
661
662
663
# File 'lib/uvc.rb', line 657

def self.video_control_interface_settings_of(device)
	video_control_interface_settings = device.interfaces.flat_map {|interface|
		interface.alt_settings.select {|setting|
			setting.bInterfaceClass == CC_VIDEO && setting.bInterfaceSubClass == SC_VIDEOCONTROL
		}
	}
end

Instance Method Details

#camera_terminalsObject



672
673
674
# File 'lib/uvc.rb', line 672

def camera_terminals
	@descriptors.select {|i| i.kind_of? CameraTerminalDescriptor }
end

#closeObject



710
711
712
713
714
# File 'lib/uvc.rb', line 710

def close
	handle = @handle
	@handle = nil
	handle.close
end

#error_codeObject



741
742
743
744
745
746
747
748
749
# File 'lib/uvc.rb', line 741

def error_code
	bRequestErrorCode = @handle.control_transfer(
		bmRequestType: 0b10100001,
		bRequest: GET_CUR,
		wValue: (VC_REQUEST_ERROR_CODE_CONTROL << 8) | 0x00,
		wIndex: @setting.bInterfaceNumber,
		dataIn: 1
	).unpack("C")[0]
end

#extension_unitsObject



684
685
686
# File 'lib/uvc.rb', line 684

def extension_units
	@descriptors.select {|i| i.kind_of? ExtensionUnitDescriptor }
end

#get_info(control_selector, entityID) ⇒ Object



1056
1057
1058
# File 'lib/uvc.rb', line 1056

def get_info(control_selector, entityID)
	Info.new(get_request(GET_INFO, control_selector, entityID, 1).unpack("B8")[0])
end

#get_len(control_selector, entityID) ⇒ Object



1060
1061
1062
# File 'lib/uvc.rb', line 1060

def get_len(control_selector, entityID)
	get_request(GET_LEN, control_selector, entityID, 1).unpack("C")[0]
end

#get_request(bRequest, control_selector, entityID, length) ⇒ Object



729
730
731
732
733
734
735
736
737
738
739
# File 'lib/uvc.rb', line 729

def get_request(bRequest, control_selector, entityID, length)
	@handle.control_transfer(
		bmRequestType: 0b10100001, # video control interface
		bRequest: bRequest,
		wValue: (control_selector << 8) | 0x00,
		wIndex: (entityID << 8) | @setting.bInterfaceNumber,
		dataIn: length
	)
rescue LIBUSB::ERROR_PIPE => e
	raise UVCError.new(error_code)
end

#input_terminalsObject



688
689
690
# File 'lib/uvc.rb', line 688

def input_terminals
	@descriptors.select {|u| u.kind_of? InputTerminalDescriptor }
end

#openObject



696
697
698
699
700
701
702
703
704
705
706
707
708
# File 'lib/uvc.rb', line 696

def open
	@handle = @setting.device.open
	if block_given?
		begin
			@handle.claim_interface(@setting.bInterfaceNumber)
			yield @handle
		ensure
			close
		end
	else
		@handle.claim_interface(@setting.bInterfaceNumber)
	end
end

#output_terminalsObject



692
693
694
# File 'lib/uvc.rb', line 692

def output_terminals
	@descriptors.select {|u| u.kind_of? OutputTerminalDescriptor }
end

#processing_unitsObject



676
677
678
# File 'lib/uvc.rb', line 676

def processing_units
	@descriptors.select {|i| i.kind_of? ProcessingUnitDescriptor }
end

#selector_unitsObject



680
681
682
# File 'lib/uvc.rb', line 680

def selector_units
	@descriptors.select {|i| i.kind_of? SelectorUnitDescriptor }
end

#set_cur(control_selector, entityID, data) ⇒ Object



1076
1077
1078
1079
1080
1081
# File 'lib/uvc.rb', line 1076

def set_cur(control_selector, entityID, data)
	control = KNOWN_CONTROLS.find {|c| c[:selector] == control_selector }
	p [:set_cur, control]
	data = control[:encode].call(data) if control
	set_request(SET_CUR, UVC.const_get(control_selector), entityID, data)
end

#set_request(bRequest, control_selector, entityID, data) ⇒ Object



716
717
718
719
720
721
722
723
724
725
726
727
# File 'lib/uvc.rb', line 716

def set_request(bRequest, control_selector, entityID, data)
	warn "set_request: %#04x %#04x %d %p" % [bRequest, control_selector, entityID, data]
	@handle.control_transfer(
		bmRequestType: 0b00100001, # video control interface
		bRequest: bRequest,
		wValue: (control_selector << 8) | 0x00,
		wIndex: (entityID << 8) | @setting.bInterfaceNumber,
		dataOut: data
	)
rescue LIBUSB::ERROR_PIPE => e
	raise UVCError.new(error_code)
end