sound/usb/hiface/chip.c

Source file repositories/reference/linux-study-clean/sound/usb/hiface/chip.c

File Facts

System
Linux kernel
Corpus path
sound/usb/hiface/chip.c
Extension
.c
Size
6783 bytes
Lines
272
Domain
Driver Families
Bucket
sound/usb
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 hiface_vendor_quirk {
	const char *device_name;
	u8 extra_freq;
};

static int hiface_chip_create(struct usb_interface *intf,
			      struct usb_device *device, int idx,
			      const struct hiface_vendor_quirk *quirk,
			      struct hiface_chip **rchip)
{
	struct snd_card *card = NULL;
	struct hiface_chip *chip;
	int ret;
	int len;

	*rchip = NULL;

	/* if we are here, card can be registered in alsa. */
	ret = snd_card_new(&intf->dev, index[idx], id[idx], THIS_MODULE,
			   sizeof(*chip), &card);
	if (ret < 0) {
		dev_err(&device->dev, "cannot create alsa card.\n");
		return ret;
	}

	strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));

	if (quirk && quirk->device_name)
		strscpy(card->shortname, quirk->device_name, sizeof(card->shortname));
	else
		strscpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));

	strlcat(card->longname, card->shortname, sizeof(card->longname));
	len = strlcat(card->longname, " at ", sizeof(card->longname));
	if (len < sizeof(card->longname))
		usb_make_path(device, card->longname + len,
			      sizeof(card->longname) - len);

	chip = card->private_data;
	chip->dev = device;
	chip->card = card;

	*rchip = chip;
	return 0;
}

static int hiface_chip_probe(struct usb_interface *intf,
			     const struct usb_device_id *usb_id)
{
	const struct hiface_vendor_quirk *quirk = (struct hiface_vendor_quirk *)usb_id->driver_info;
	int ret;
	int i;
	struct hiface_chip *chip;
	struct usb_device *device = interface_to_usbdev(intf);

	ret = usb_set_interface(device, 0, 0);
	if (ret != 0) {
		dev_err(&device->dev, "can't set first interface for " CARD_NAME " device.\n");
		return -EIO;
	}

	/* check whether the card is already registered */
	chip = NULL;
	guard(mutex)(&register_mutex);

	for (i = 0; i < SNDRV_CARDS; i++)
		if (enable[i])
			break;

	if (i >= SNDRV_CARDS) {
		dev_err(&device->dev, "no available " CARD_NAME " audio device\n");
		return -ENODEV;
	}

	ret = hiface_chip_create(intf, device, i, quirk, &chip);
	if (ret < 0)
		return ret;

	ret = hiface_pcm_init(chip, quirk ? quirk->extra_freq : 0);
	if (ret < 0)
		goto err_chip_destroy;

	ret = snd_card_register(chip->card);
	if (ret < 0) {
		dev_err(&device->dev, "cannot register " CARD_NAME " card\n");
		goto err_chip_destroy;
	}

	usb_set_intfdata(intf, chip);
	return 0;

Annotation

Implementation Notes