drivers/media/radio/dsbr100.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/radio/dsbr100.c
Extension
.c
Size
11778 bytes
Lines
421
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 dsbr100_device {
	struct usb_device *usbdev;
	struct video_device videodev;
	struct v4l2_device v4l2_dev;
	struct v4l2_ctrl_handler hdl;

	u8 *transfer_buffer;
	struct mutex v4l2_lock;
	int curfreq;
	bool stereo;
	bool muted;
};

/* Low-level device interface begins here */

/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
static int dsbr100_setfreq(struct dsbr100_device *radio, unsigned freq)
{
	unsigned f = (freq / 16 * 80) / 1000 + 856;
	int retval = 0;

	if (!radio->muted) {
		retval = usb_control_msg(radio->usbdev,
				usb_rcvctrlpipe(radio->usbdev, 0),
				DSB100_TUNE,
				USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
				(f >> 8) & 0x00ff, f & 0xff,
				radio->transfer_buffer, 8, 300);
		if (retval >= 0)
			mdelay(1);
	}

	if (retval >= 0) {
		radio->curfreq = freq;
		return 0;
	}
	dev_err(&radio->usbdev->dev,
		"%s - usb_control_msg returned %i, request %i\n",
			__func__, retval, DSB100_TUNE);
	return retval;
}

/* switch on radio */
static int dsbr100_start(struct dsbr100_device *radio)
{
	int retval = usb_control_msg(radio->usbdev,
		usb_rcvctrlpipe(radio->usbdev, 0),
		DSB100_ONOFF,
		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
		0x01, 0x00, radio->transfer_buffer, 8, 300);

	if (retval >= 0)
		return dsbr100_setfreq(radio, radio->curfreq);
	dev_err(&radio->usbdev->dev,
		"%s - usb_control_msg returned %i, request %i\n",
			__func__, retval, DSB100_ONOFF);
	return retval;

}

/* switch off radio */
static int dsbr100_stop(struct dsbr100_device *radio)
{
	int retval = usb_control_msg(radio->usbdev,
		usb_rcvctrlpipe(radio->usbdev, 0),
		DSB100_ONOFF,
		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
		0x00, 0x00, radio->transfer_buffer, 8, 300);

	if (retval >= 0)
		return 0;
	dev_err(&radio->usbdev->dev,
		"%s - usb_control_msg returned %i, request %i\n",
			__func__, retval, DSB100_ONOFF);
	return retval;

}

/* return the device status.  This is, in effect, just whether it
sees a stereo signal or not.  Pity. */
static void dsbr100_getstat(struct dsbr100_device *radio)
{
	int retval = usb_control_msg(radio->usbdev,
		usb_rcvctrlpipe(radio->usbdev, 0),
		USB_REQ_GET_STATUS,
		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
		0x00, 0x24, radio->transfer_buffer, 8, 300);

	if (retval < 0) {
		radio->stereo = false;

Annotation

Implementation Notes