drivers/media/radio/radio-ma901.c

Source file repositories/reference/linux-study-clean/drivers/media/radio/radio-ma901.c

File Facts

System
Linux kernel
Corpus path
drivers/media/radio/radio-ma901.c
Extension
.c
Size
12779 bytes
Lines
457
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ma901radio_device {
	/* reference to USB and video device */
	struct usb_device *usbdev;
	struct usb_interface *intf;
	struct video_device vdev;
	struct v4l2_device v4l2_dev;
	struct v4l2_ctrl_handler hdl;

	u8 *buffer;
	struct mutex lock;	/* buffer locking */
	int curfreq;
	u16 volume;
	int stereo;
	bool muted;
};

static inline struct ma901radio_device *to_ma901radio_dev(struct v4l2_device *v4l2_dev)
{
	return container_of(v4l2_dev, struct ma901radio_device, v4l2_dev);
}

/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
static int ma901radio_set_freq(struct ma901radio_device *radio, int freq)
{
	unsigned int freq_send = 0x300 + (freq >> 5) / 25;
	int retval;

	radio->buffer[0] = 0x0a;
	radio->buffer[1] = MA901_RADIO_SET_FREQ;
	radio->buffer[2] = ((freq_send >> 8) & 0xff) + 0x80;
	radio->buffer[3] = freq_send & 0xff;
	radio->buffer[4] = 0x00;
	radio->buffer[5] = 0x00;
	radio->buffer[6] = 0x00;
	radio->buffer[7] = 0x00;

	retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
				9, 0x21, 0x0300, 0,
				radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
	if (retval < 0)
		return retval;

	radio->curfreq = freq;
	return 0;
}

static int ma901radio_set_volume(struct ma901radio_device *radio, u16 vol_to_set)
{
	int retval;

	radio->buffer[0] = 0x0a;
	radio->buffer[1] = MA901_RADIO_SET_VOLUME;
	radio->buffer[2] = 0xc2;
	radio->buffer[3] = vol_to_set + 0x20;
	radio->buffer[4] = 0x00;
	radio->buffer[5] = 0x00;
	radio->buffer[6] = 0x00;
	radio->buffer[7] = 0x00;

	retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
				9, 0x21, 0x0300, 0,
				radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);
	if (retval < 0)
		return retval;

	radio->volume = vol_to_set;
	return retval;
}

static int ma901_set_stereo(struct ma901radio_device *radio, u8 stereo)
{
	int retval;

	radio->buffer[0] = 0x0a;
	radio->buffer[1] = MA901_RADIO_SET_MONO_STEREO;
	radio->buffer[2] = stereo;
	radio->buffer[3] = 0x00;
	radio->buffer[4] = 0x00;
	radio->buffer[5] = 0x00;
	radio->buffer[6] = 0x00;
	radio->buffer[7] = 0x00;

	retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0),
				9, 0x21, 0x0300, 0,
				radio->buffer, BUFFER_LENGTH, USB_TIMEOUT);

	if (retval < 0)
		return retval;

	if (stereo == MA901_WANT_STEREO)

Annotation

Implementation Notes