Exemplo n.º 1
0
static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_request cm,
			       u32 *data, int size)
{
	int ret, len;
	__le32 *buf;
	int offb;
	unsigned int offd;
	const int stride = CMD_PACKET_SIZE / (4 * 2) - 1;
	int buflen =  ((size - 1) / stride + 1 + size * 2) * 4;

	buf = kmalloc(buflen, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	ret = cxacru_cm(instance, cm, NULL, 0, (u8 *) buf, buflen);
	if (ret < 0)
		goto cleanup;

	/* len > 0 && len % 4 == 0 guaranteed by cxacru_cm() */
	len = ret / 4;
	for (offb = 0; offb < len; ) {
		int l = le32_to_cpu(buf[offb++]);

		if (l < 0 || l > stride || l > (len - offb) / 2) {
			if (printk_ratelimit())
				usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n",
					cm, l);
			ret = -EIO;
			goto cleanup;
		}
		while (l--) {
			offd = le32_to_cpu(buf[offb++]);
			if (offd >= size) {
				if (printk_ratelimit())
					usb_err(instance->usbatm, "wrong index %#x in response to cm %#x\n",
						offd, cm);
				ret = -EIO;
				goto cleanup;
			}
			data[offd] = le32_to_cpu(buf[offb++]);
		}
	}

	ret = 0;

cleanup:
	kfree(buf);
	return ret;
}
Exemplo n.º 2
0
static int speedtch_find_firmware(struct usbatm_data *usbatm, struct usb_interface *intf,
				  int phase, const struct firmware **fw_p)
{
	struct device *dev = &intf->dev;
	const u16 bcdDevice = le16_to_cpu(interface_to_usbdev(intf)->descriptor.bcdDevice);
	const u8 major_revision = bcdDevice >> 8;
	const u8 minor_revision = bcdDevice & 0xff;
	char buf[24];

	sprintf(buf, "speedtch-%d.bin.%x.%02x", phase, major_revision, minor_revision);
	usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);

	if (request_firmware(fw_p, buf, dev)) {
		sprintf(buf, "speedtch-%d.bin.%x", phase, major_revision);
		usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);

		if (request_firmware(fw_p, buf, dev)) {
			sprintf(buf, "speedtch-%d.bin", phase);
			usb_dbg(usbatm, "%s: looking for %s\n", __func__, buf);

			if (request_firmware(fw_p, buf, dev)) {
				usb_err(usbatm, "%s: no stage %d firmware found!\n", __func__, phase);
				return -ENOENT;
			}
		}
	}

	usb_info(usbatm, "found stage %d firmware %s\n", phase, buf);

	return 0;
}
Exemplo n.º 3
0
static int xusbatm_capture_intf(struct usbatm_data *usbatm, struct usb_device *usb_dev,
		struct usb_interface *intf, int altsetting, int claim)
{
	int ifnum = intf->altsetting->desc.bInterfaceNumber;
	int ret;

	if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
		usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
		return ret;
	}
	if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
		usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
		return ret;
	}
	return 0;
}
Exemplo n.º 4
0
/**
 * Get a USB configuration descriptor based on its index.
 */
int  libusb_get_config_descriptor(libusb_device *dev,
	uint8_t config_index, struct libusb_config_descriptor **config)
{
	struct libusb_config_descriptor *_config;
	unsigned char tmp[8];
	unsigned char *buf = NULL;
	int host_endian = 0;
	int r;

	usb_dbg("index %d", config_index);
	if (config_index >= dev->num_configurations)
		return LIBUSB_ERROR_NOT_FOUND;

	_config = malloc(sizeof(*_config));
	if (!_config)
		return LIBUSB_ERROR_NO_MEM;

	r = usb_backend->get_config_descriptor(dev, config_index, tmp,
		sizeof(tmp), &host_endian);
	if (r < 0)
		goto err;

	usb_parse_descriptor(tmp, "bbw", _config, host_endian);
	buf = malloc(_config->wTotalLength);
	if (!buf) {
		r = LIBUSB_ERROR_NO_MEM;
		goto err;
	}

	host_endian = 0;
	r = usb_backend->get_config_descriptor(dev, config_index, buf,
		_config->wTotalLength, &host_endian);
	if (r < 0)
		goto err;

	r = parse_configuration(dev->ctx, _config, buf, host_endian);
	if (r < 0) {
		usb_err(dev->ctx, "parse_configuration failed with error %d", r);
		goto err;
	} else if (r > 0) {
		usb_warn(dev->ctx, "descriptor data still left");
	}

	free(buf);
	*config = _config;
	return 0;

err:
	free(_config);
	if (buf)
		free(buf);
	return r;
}
Exemplo n.º 5
0
static int xusbatm_bind(struct usbatm_data *usbatm,
			struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *usb_dev = interface_to_usbdev(intf);
	int drv_ix = id - xusbatm_usb_ids;
	int rx_alt = rx_altsetting[drv_ix];
	int tx_alt = tx_altsetting[drv_ix];
	struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
	struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
	int ret;

	usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
		" rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
		__func__, drv_ix, vendor[drv_ix], product[drv_ix],
		rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
		tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);

	if (!rx_intf || !tx_intf) {
		if (!rx_intf)
			usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
				__func__, rx_endpoint[drv_ix], rx_alt);
		if (!tx_intf)
			usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
				__func__, tx_endpoint[drv_ix], tx_alt);
		return -ENODEV;
	}

	if ((rx_intf != intf) && (tx_intf != intf))
		return -ENODEV;

	if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
		usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
				rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
		return -EINVAL;
	}

	usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
			rx_intf->altsetting->desc.bInterfaceNumber,
			tx_intf->altsetting->desc.bInterfaceNumber);

	ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf);
	if (ret)
		return ret;

	if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
		xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
		return ret;
	}

	return 0;
}
static int dwc_otg_hi6250_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct otg_dev *dev_p = NULL;

	dev_p = devm_kzalloc(&pdev->dev, sizeof(*dev_p), GFP_KERNEL);
	if (!dev_p) {
		usb_err("alloc otg_dev failed! not enough memory\n");
		return -ENOMEM;
	}
	dev_p->pdev = pdev;

	register_usb_phy_ops(dev_p, &hi6250_usb_phy_ops);

	ret = dwc_otg_hicommon_probe(dev_p); /* usb common interface */

	return ret;
}
int hi6250_enable_abb_clk(struct otg_dev *otg_device)
{
	void __iomem *pctrl_base = otg_device->pctrl_reg_base;
	uint32_t temp = 0;
	int ret = 0;

	/* config and switch on abb clk */
	temp = readl(pctrl_base + PCTRL_PERI_CTRL24);
	temp &= ~(7 << 24);
	temp |= (5 << 24);
	writel(temp, pctrl_base + PCTRL_PERI_CTRL24);

	/* enable abb clk */
	ret = clk_prepare_enable(otg_device->clk);
	if (ret) {
		usb_err("[USB2.0]:clk_prepare_enable failed:%d\n", ret);
		return ret;
	}

	return 0;
}
Exemplo n.º 8
0
static int speedtch_heavy_init(struct usbatm_data *usbatm, struct usb_interface *intf)
{
	const struct firmware *fw1, *fw2;
	struct speedtch_instance_data *instance = usbatm->driver_data;
	int ret;

	if ((ret = speedtch_find_firmware(usbatm, intf, 1, &fw1)) < 0)
		return ret;

	if ((ret = speedtch_find_firmware(usbatm, intf, 2, &fw2)) < 0) {
		release_firmware(fw1);
		return ret;
	}

	if ((ret = speedtch_upload_firmware(instance, fw1, fw2)) < 0)
		usb_err(usbatm, "%s: firmware upload failed (%d)!\n", __func__, ret);

	release_firmware(fw2);
	release_firmware(fw1);

	return ret;
}
Exemplo n.º 9
0
static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
				     const struct firmware *fw1,
				     const struct firmware *fw2)
{
	unsigned char *buffer;
	struct usbatm_data *usbatm = instance->usbatm;
	struct usb_interface *intf;
	struct usb_device *usb_dev = usbatm->usb_dev;
	int actual_length;
	int ret = 0;
	int offset;

	usb_dbg(usbatm, "%s entered\n", __func__);

	if (!(buffer = (unsigned char *)__get_free_page(GFP_KERNEL))) {
		ret = -ENOMEM;
		usb_dbg(usbatm, "%s: no memory for buffer!\n", __func__);
		goto out;
	}

	if (!(intf = usb_ifnum_to_if(usb_dev, 2))) {
		ret = -ENODEV;
		usb_dbg(usbatm, "%s: interface not found!\n", __func__);
		goto out_free;
	}

	/* URB 7 */
	if (dl_512_first) {	/* some modems need a read before writing the firmware */
		ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),
				   buffer, 0x200, &actual_length, 2000);

		if (ret < 0 && ret != -ETIMEDOUT)
			usb_warn(usbatm, "%s: read BLOCK0 from modem failed (%d)!\n", __func__, ret);
		else
			usb_dbg(usbatm, "%s: BLOCK0 downloaded (%d bytes)\n", __func__, ret);
	}

	/* URB 8 : both leds are static green */
	for (offset = 0; offset < fw1->size; offset += PAGE_SIZE) {
		int thislen = min_t(int, PAGE_SIZE, fw1->size - offset);
		memcpy(buffer, fw1->data + offset, thislen);

		ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE),
				   buffer, thislen, &actual_length, DATA_TIMEOUT);

		if (ret < 0) {
			usb_err(usbatm, "%s: write BLOCK1 to modem failed (%d)!\n", __func__, ret);
			goto out_free;
		}
		usb_dbg(usbatm, "%s: BLOCK1 uploaded (%zu bytes)\n", __func__, fw1->size);
	}

	/* USB led blinking green, ADSL led off */

	/* URB 11 */
	ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),
			   buffer, 0x200, &actual_length, DATA_TIMEOUT);

	if (ret < 0) {
		usb_err(usbatm, "%s: read BLOCK2 from modem failed (%d)!\n", __func__, ret);
		goto out_free;
	}
	usb_dbg(usbatm, "%s: BLOCK2 downloaded (%d bytes)\n", __func__, actual_length);

	/* URBs 12 to 139 - USB led blinking green, ADSL led off */
	for (offset = 0; offset < fw2->size; offset += PAGE_SIZE) {
		int thislen = min_t(int, PAGE_SIZE, fw2->size - offset);
		memcpy(buffer, fw2->data + offset, thislen);

		ret = usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, ENDPOINT_FIRMWARE),
				   buffer, thislen, &actual_length, DATA_TIMEOUT);

		if (ret < 0) {
			usb_err(usbatm, "%s: write BLOCK3 to modem failed (%d)!\n", __func__, ret);
			goto out_free;
		}
	}
	usb_dbg(usbatm, "%s: BLOCK3 uploaded (%zu bytes)\n", __func__, fw2->size);

	/* USB led static green, ADSL led static red */

	/* URB 142 */
	ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, ENDPOINT_FIRMWARE),
			   buffer, 0x200, &actual_length, DATA_TIMEOUT);

	if (ret < 0) {
		usb_err(usbatm, "%s: read BLOCK4 from modem failed (%d)!\n", __func__, ret);
		goto out_free;
	}

	/* success */
	usb_dbg(usbatm, "%s: BLOCK4 downloaded (%d bytes)\n", __func__, actual_length);

	/* Delay to allow firmware to start up. We can do this here
	   because we're in our own kernel thread anyway. */
	msleep_interruptible(1000);

	if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) {
		usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret);
		goto out_free;
	}

	/* Enable software buffering, if requested */
	if (sw_buffering)
		speedtch_set_swbuff(instance, 1);

	/* Magic spell; don't ask us what this does */
	speedtch_test_sequence(instance);

	ret = 0;

out_free:
	free_page((unsigned long)buffer);
out:
	return ret;
}
Exemplo n.º 10
0
static int parse_interface(libusb_context *ctx,
	struct libusb_interface *usb_interface, unsigned char *buffer, int size,
	int host_endian)
{
	int i;
	int len;
	int r;
	int parsed = 0;
	size_t tmp;
	struct usb_descriptor_header header;
	struct libusb_interface_descriptor *ifp;
	unsigned char *begin;

	usb_interface->num_altsetting = 0;

	while (size >= INTERFACE_DESC_LENGTH) {
		struct libusb_interface_descriptor *altsetting =
			(struct libusb_interface_descriptor *) usb_interface->altsetting;
		altsetting = realloc(altsetting,
			sizeof(struct libusb_interface_descriptor) *
			(usb_interface->num_altsetting + 1));
		if (!altsetting) {
			r = LIBUSB_ERROR_NO_MEM;
			goto err;
		}
		usb_interface->altsetting = altsetting;

		ifp = altsetting + usb_interface->num_altsetting;
		usb_interface->num_altsetting++;
		usb_parse_descriptor(buffer, "bbbbbbbbb", ifp, 0);
		ifp->extra = NULL;
		ifp->extra_length = 0;
		ifp->endpoint = NULL;

		/* Skip over the interface */
		buffer += ifp->bLength;
		parsed += ifp->bLength;
		size -= ifp->bLength;

		begin = buffer;

		/* Skip over any interface, class or vendor descriptors */
		while (size >= DESC_HEADER_LENGTH) {
			usb_parse_descriptor(buffer, "bb", &header, 0);
			if (header.bLength < 2) {
				usb_err(ctx, "invalid descriptor of length %d",
					header.bLength);
				r = LIBUSB_ERROR_IO;
				goto err;
			}

			/* If we find another "proper" descriptor then we're done */
			if ((header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
					(header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
					(header.bDescriptorType == LIBUSB_DT_DEVICE))
				break;

			buffer += header.bLength;
			parsed += header.bLength;
			size -= header.bLength;
		}

		/* Copy any unknown descriptors into a storage area for */
		/*  drivers to later parse */
		len = (int)(buffer - begin);
		if (len) {
			ifp->extra = malloc(len);
			if (!ifp->extra) {
				r = LIBUSB_ERROR_NO_MEM;
				goto err;
			}
			memcpy((unsigned char *) ifp->extra, begin, len);
			ifp->extra_length = len;
		}

		/* Did we hit an unexpected descriptor? */
		if (size >= DESC_HEADER_LENGTH) {
			usb_parse_descriptor(buffer, "bb", &header, 0);
			if ((header.bDescriptorType == LIBUSB_DT_CONFIG) ||
			    (header.bDescriptorType == LIBUSB_DT_DEVICE)) {
				return parsed;
			}
		}

		if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
			usb_err(ctx, "too many endpoints (%d)", ifp->bNumEndpoints);
			r = LIBUSB_ERROR_IO;
			goto err;
		}

		if (ifp->bNumEndpoints > 0) {
			struct libusb_endpoint_descriptor *endpoint;
			tmp = ifp->bNumEndpoints * sizeof(struct libusb_endpoint_descriptor);
			endpoint = malloc(tmp);
			ifp->endpoint = endpoint;
			if (!endpoint) {
				r = LIBUSB_ERROR_NO_MEM;
				goto err;
			}

			memset(endpoint, 0, tmp);
			for (i = 0; i < ifp->bNumEndpoints; i++) {
				usb_parse_descriptor(buffer, "bb", &header, 0);

				if (header.bLength > size) {
					usb_err(ctx, "ran out of descriptors parsing");
					r = LIBUSB_ERROR_IO;
					goto err;
				}

				r = parse_endpoint(ctx, endpoint + i, buffer, size,
					host_endian);
				if (r < 0)
					goto err;

				buffer += r;
				parsed += r;
				size -= r;
			}
		}

		/* We check to see if it's an alternate to this one */
		ifp = (struct libusb_interface_descriptor *) buffer;
		if (size < LIBUSB_DT_INTERFACE_SIZE ||
				ifp->bDescriptorType != LIBUSB_DT_INTERFACE ||
				!ifp->bAlternateSetting)
			return parsed;
	}

	return parsed;
err:
	clear_interface(usb_interface);
	return r;
}
Exemplo n.º 11
0
static void cxacru_upload_firmware(struct cxacru_data *instance,
				   const struct firmware *fw,
				   const struct firmware *bp)
{
	int ret;
	struct usbatm_data *usbatm = instance->usbatm;
	struct usb_device *usb_dev = usbatm->usb_dev;
	__le16 signature[] = { usb_dev->descriptor.idVendor,
			       usb_dev->descriptor.idProduct };
	__le32 val;

	dbg("cxacru_upload_firmware");

	/* FirmwarePllFClkValue */
	val = cpu_to_le32(instance->modem_type->pll_f_clk);
	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4);
	if (ret) {
		usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret);
		return;
	}

	/* FirmwarePllBClkValue */
	val = cpu_to_le32(instance->modem_type->pll_b_clk);
	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4);
	if (ret) {
		usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret);
		return;
	}

	/* Enable SDRAM */
	val = cpu_to_le32(SDRAM_ENA);
	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4);
	if (ret) {
		usb_err(usbatm, "Enable SDRAM failed: %d\n", ret);
		return;
	}

	/* Firmware */
	usb_info(usbatm, "loading firmware\n");
	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size);
	if (ret) {
		usb_err(usbatm, "Firmware upload failed: %d\n", ret);
		return;
	}

	/* Boot ROM patch */
	if (instance->modem_type->boot_rom_patch) {
		usb_info(usbatm, "loading boot ROM patch\n");
		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size);
		if (ret) {
			usb_err(usbatm, "Boot ROM patching failed: %d\n", ret);
			return;
		}
	}

	/* Signature */
	ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4);
	if (ret) {
		usb_err(usbatm, "Signature storing failed: %d\n", ret);
		return;
	}

	usb_info(usbatm, "starting device\n");
	if (instance->modem_type->boot_rom_patch) {
		val = cpu_to_le32(BR_ADDR);
		ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4);
	} else {
		ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0);
	}
	if (ret) {
		usb_err(usbatm, "Passing control to firmware failed: %d\n", ret);
		return;
	}

	/* Delay to allow firmware to start up. */
	msleep_interruptible(1000);

	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD));
	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD));
	usb_clear_halt(usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_DATA));
	usb_clear_halt(usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_DATA));

	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
	if (ret < 0) {
		usb_err(usbatm, "modem failed to initialize: %d\n", ret);
		return;
	}
}
Exemplo n.º 12
0
static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm,
		     u8 *wdata, int wsize, u8 *rdata, int rsize)
{
	int ret, actlen;
	int offb, offd;
	const int stride = CMD_PACKET_SIZE - 4;
	u8 *wbuf = instance->snd_buf;
	u8 *rbuf = instance->rcv_buf;
	int wbuflen = ((wsize - 1) / stride + 1) * CMD_PACKET_SIZE;
	int rbuflen = ((rsize - 1) / stride + 1) * CMD_PACKET_SIZE;

	if (wbuflen > PAGE_SIZE || rbuflen > PAGE_SIZE) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n",
				wbuflen, rbuflen);
		ret = -ENOMEM;
		goto err;
	}

	mutex_lock(&instance->cm_serialize);

	/* submit reading urb before the writing one */
	init_completion(&instance->rcv_done);
	ret = usb_submit_urb(instance->rcv_urb, GFP_KERNEL);
	if (ret < 0) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "submit of read urb for cm %#x failed (%d)\n",
				cm, ret);
		goto fail;
	}

	memset(wbuf, 0, wbuflen);
	/* handle wsize == 0 */
	wbuf[0] = cm;
	for (offb = offd = 0; offd < wsize; offd += stride, offb += CMD_PACKET_SIZE) {
		wbuf[offb] = cm;
		memcpy(wbuf + offb + 4, wdata + offd, min_t(int, stride, wsize - offd));
	}

	instance->snd_urb->transfer_buffer_length = wbuflen;
	init_completion(&instance->snd_done);
	ret = usb_submit_urb(instance->snd_urb, GFP_KERNEL);
	if (ret < 0) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "submit of write urb for cm %#x failed (%d)\n",
				cm, ret);
		goto fail;
	}

	ret = cxacru_start_wait_urb(instance->snd_urb, &instance->snd_done, NULL);
	if (ret < 0) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "send of cm %#x failed (%d)\n", cm, ret);
		goto fail;
	}

	ret = cxacru_start_wait_urb(instance->rcv_urb, &instance->rcv_done, &actlen);
	if (ret < 0) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "receive of cm %#x failed (%d)\n", cm, ret);
		goto fail;
	}
	if (actlen % CMD_PACKET_SIZE || !actlen) {
		if (printk_ratelimit())
			usb_err(instance->usbatm, "invalid response length to cm %#x: %d\n",
				cm, actlen);
		ret = -EIO;
		goto fail;
	}

	/* check the return status and copy the data to the output buffer, if needed */
	for (offb = offd = 0; offd < rsize && offb < actlen; offb += CMD_PACKET_SIZE) {
		if (rbuf[offb] != cm) {
			if (printk_ratelimit())
				usb_err(instance->usbatm, "wrong cm %#x in response to cm %#x\n",
					rbuf[offb], cm);
			ret = -EIO;
			goto fail;
		}
		if (rbuf[offb + 1] != CM_STATUS_SUCCESS) {
			if (printk_ratelimit())
				usb_err(instance->usbatm, "response to cm %#x failed: %#x\n",
					cm, rbuf[offb + 1]);
			ret = -EIO;
			goto fail;
		}
		if (offd >= rsize)
			break;
		memcpy(rdata + offd, rbuf + offb + 4, min_t(int, stride, rsize - offd));
		offd += stride;
	}

	ret = offd;
	dbg("cm %#x", cm);
fail:
	mutex_unlock(&instance->cm_serialize);
err:
	return ret;
}
Exemplo n.º 13
0
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
		struct atm_dev *atm_dev)
{
	struct cxacru_data *instance = usbatm_instance->driver_data;
	struct usb_interface *intf = usbatm_instance->usb_intf;
	int ret;
	int start_polling = 1;

	dbg("cxacru_atm_start");

	/* Read MAC address */
	ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_MAC_ADDRESS, NULL, 0,
			atm_dev->esi, sizeof(atm_dev->esi));
	if (ret < 0) {
		atm_err(usbatm_instance, "cxacru_atm_start: CARD_GET_MAC_ADDRESS returned %d\n", ret);
		return ret;
	}

	#define CXACRU_DEVICE_CREATE_FILE(_name) \
		ret = device_create_file(&intf->dev, &dev_attr_##_name); \
		if (unlikely(ret)) \
			goto fail_sysfs;
	CXACRU_ALL_FILES(CREATE);
	#undef CXACRU_DEVICE_CREATE_FILE

	/* start ADSL */
	mutex_lock(&instance->adsl_state_serialize);
	ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
	if (ret < 0)
		atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);

	/* Start status polling */
	mutex_lock(&instance->poll_state_serialize);
	switch (instance->poll_state) {
	case CXPOLL_STOPPED:
		/* start polling */
		instance->poll_state = CXPOLL_POLLING;
		break;

	case CXPOLL_STOPPING:
		/* abort stop request */
		instance->poll_state = CXPOLL_POLLING;
	case CXPOLL_POLLING:
	case CXPOLL_SHUTDOWN:
		/* don't start polling */
		start_polling = 0;
	}
	mutex_unlock(&instance->poll_state_serialize);
	mutex_unlock(&instance->adsl_state_serialize);

	printk(KERN_INFO "%s%d: %s %pM\n", atm_dev->type, atm_dev->number,
			usbatm_instance->description, atm_dev->esi);

	if (start_polling)
		cxacru_poll_status(&instance->poll_work.work);
	return 0;

fail_sysfs:
	usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
	cxacru_remove_device_files(usbatm_instance, atm_dev);
	return ret;
}
Exemplo n.º 14
0
static int parse_configuration(struct libusb_context *ctx,
	struct libusb_config_descriptor *config, unsigned char *buffer,
	int host_endian)
{
	int i;
	int r;
	int size;
	size_t tmp;
	struct usb_descriptor_header header;
	struct libusb_interface *usb_interface;

	usb_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
	size = config->wTotalLength;

	if (config->bNumInterfaces > USB_MAXINTERFACES) {
		usb_err(ctx, "too many interfaces (%d)", config->bNumInterfaces);
		return LIBUSB_ERROR_IO;
	}

	tmp = config->bNumInterfaces * sizeof(struct libusb_interface);
	usb_interface = malloc(tmp);
	config->interface = usb_interface;
	if (!config->interface)
		return LIBUSB_ERROR_NO_MEM;

	memset(usb_interface, 0, tmp);
	buffer += config->bLength;
	size -= config->bLength;

	config->extra = NULL;
	config->extra_length = 0;

	for (i = 0; i < config->bNumInterfaces; i++) {
		int len;
		unsigned char *begin;

		/* Skip over the rest of the Class Specific or Vendor */
		/*  Specific descriptors */
		begin = buffer;
		while (size >= DESC_HEADER_LENGTH) {
			usb_parse_descriptor(buffer, "bb", &header, 0);

			if ((header.bLength > size) ||
					(header.bLength < DESC_HEADER_LENGTH)) {
				usb_err(ctx, "invalid descriptor length of %d",
					header.bLength);
				r = LIBUSB_ERROR_IO;
				goto err;
			}

			/* If we find another "proper" descriptor then we're done */
			if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
					(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
					(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
					(header.bDescriptorType == LIBUSB_DT_DEVICE))
				break;

			usb_dbg("skipping descriptor 0x%x\n", header.bDescriptorType);
			buffer += header.bLength;
			size -= header.bLength;
		}

		/* Copy any unknown descriptors into a storage area for */
		/*  drivers to later parse */
		len = (int)(buffer - begin);
		if (len) {
			/* FIXME: We should realloc and append here */
			if (!config->extra_length) {
				config->extra = malloc(len);
				if (!config->extra) {
					r = LIBUSB_ERROR_NO_MEM;
					goto err;
				}

				memcpy((unsigned char *) config->extra, begin, len);
				config->extra_length = len;
			}
		}

		r = parse_interface(ctx, usb_interface + i, buffer, size, host_endian);
		if (r < 0)
			goto err;

		buffer += r;
		size -= r;
	}

	return size;

err:
	clear_configuration(config);
	return r;
}
Exemplo n.º 15
0
static int parse_endpoint(struct libusb_context *ctx,
	struct libusb_endpoint_descriptor *endpoint, unsigned char *buffer,
	int size, int host_endian)
{
	struct usb_descriptor_header header;
	unsigned char *extra;
	unsigned char *begin;
	int parsed = 0;
	int len;

	usb_parse_descriptor(buffer, "bb", &header, 0);

	/* Everything should be fine being passed into here, but we sanity */
	/*  check JIC */
	if (header.bLength > size) {
		usb_err(ctx, "ran out of descriptors parsing");
		return -1;
	}

	if (header.bDescriptorType != LIBUSB_DT_ENDPOINT) {
		usb_err(ctx, "unexpected descriptor %x (expected %x)",
			header.bDescriptorType, LIBUSB_DT_ENDPOINT);
		return parsed;
	}

	if (header.bLength >= ENDPOINT_AUDIO_DESC_LENGTH)
		usb_parse_descriptor(buffer, "bbbbwbbb", endpoint, host_endian);
	else if (header.bLength >= ENDPOINT_DESC_LENGTH)
		usb_parse_descriptor(buffer, "bbbbwb", endpoint, host_endian);

	buffer += header.bLength;
	size -= header.bLength;
	parsed += header.bLength;

	/* Skip over the rest of the Class Specific or Vendor Specific */
	/*  descriptors */
	begin = buffer;
	while (size >= DESC_HEADER_LENGTH) {
		usb_parse_descriptor(buffer, "bb", &header, 0);

		if (header.bLength < 2) {
			usb_err(ctx, "invalid descriptor length %d", header.bLength);
			return -1;
		}

		/* If we find another "proper" descriptor then we're done  */
		if ((header.bDescriptorType == LIBUSB_DT_ENDPOINT) ||
				(header.bDescriptorType == LIBUSB_DT_INTERFACE) ||
				(header.bDescriptorType == LIBUSB_DT_CONFIG) ||
				(header.bDescriptorType == LIBUSB_DT_DEVICE))
			break;

		usb_dbg("skipping descriptor %x", header.bDescriptorType);
		buffer += header.bLength;
		size -= header.bLength;
		parsed += header.bLength;
	}

	/* Copy any unknown descriptors into a storage area for drivers */
	/*  to later parse */
	len = (int)(buffer - begin);
	if (!len) {
		endpoint->extra = NULL;
		endpoint->extra_length = 0;
		return parsed;
	}

	extra = malloc(len);
	endpoint->extra = extra;
	if (!extra) {
		endpoint->extra_length = 0;
		return LIBUSB_ERROR_NO_MEM;
	}

	memcpy(extra, begin, len);
	endpoint->extra_length = len;

	return parsed;
}
Exemplo n.º 16
0
static int chaoskey_probe(struct usb_interface *interface,
			  const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *altsetting = interface->cur_altsetting;
	int i;
	int in_ep = -1;
	struct chaoskey *dev;
	int result;
	int size;

	usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);

	/* Find the first bulk IN endpoint and its packet size */
	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
		if (usb_endpoint_is_bulk_in(&altsetting->endpoint[i].desc)) {
			in_ep = usb_endpoint_num(&altsetting->endpoint[i].desc);
			size = usb_endpoint_maxp(&altsetting->endpoint[i].desc);
			break;
		}
	}

	/* Validate endpoint and size */
	if (in_ep == -1) {
		usb_dbg(interface, "no IN endpoint found");
		return -ENODEV;
	}
	if (size <= 0) {
		usb_dbg(interface, "invalid size (%d)", size);
		return -ENODEV;
	}

	if (size > CHAOSKEY_BUF_LEN) {
		usb_dbg(interface, "size reduced from %d to %d\n",
			size, CHAOSKEY_BUF_LEN);
		size = CHAOSKEY_BUF_LEN;
	}

	/* Looks good, allocate and initialize */

	dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);

	if (dev == NULL)
		return -ENOMEM;

	dev->buf = kmalloc(size, GFP_KERNEL);

	if (dev->buf == NULL) {
		kfree(dev);
		return -ENOMEM;
	}

	/* Construct a name using the product and serial values. Each
	 * device needs a unique name for the hwrng code
	 */

	if (udev->product && udev->serial) {
		dev->name = kmalloc(strlen(udev->product) + 1 +
				    strlen(udev->serial) + 1, GFP_KERNEL);
		if (dev->name == NULL) {
			kfree(dev->buf);
			kfree(dev);
			return -ENOMEM;
		}

		strcpy(dev->name, udev->product);
		strcat(dev->name, "-");
		strcat(dev->name, udev->serial);
	}

	dev->interface = interface;

	dev->in_ep = in_ep;

	dev->size = size;
	dev->present = 1;

	init_waitqueue_head(&dev->wait_q);

	mutex_init(&dev->lock);
	mutex_init(&dev->rng_lock);

	usb_set_intfdata(interface, dev);

	result = usb_register_dev(interface, &chaoskey_class);
	if (result) {
		usb_err(interface, "Unable to allocate minor number.");
		usb_set_intfdata(interface, NULL);
		chaoskey_free(dev);
		return result;
	}

	dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
	dev->hwrng.read = chaoskey_rng_read;

	/* Set the 'quality' metric.  Quality is measured in units of
	 * 1/1024's of a bit ("mills"). This should be set to 1024,
	 * but there is a bug in the hwrng core which masks it with
	 * 1023.
	 *
	 * The patch that has been merged to the crypto development
	 * tree for that bug limits the value to 1024 at most, so by
	 * setting this to 1024 + 1023, we get 1023 before the fix is
	 * merged and 1024 afterwards. We'll patch this driver once
	 * both bits of code are in the same tree.
	 */
	dev->hwrng.quality = 1024 + 1023;

	dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
	if (!dev->hwrng_registered)
		usb_err(interface, "Unable to register with hwrng");

	usb_enable_autosuspend(udev);

	usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
	return 0;
}
Exemplo n.º 17
0
static int chaoskey_probe(struct usb_interface *interface,
			  const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *altsetting = interface->cur_altsetting;
	struct usb_endpoint_descriptor *epd;
	int in_ep;
	struct chaoskey *dev;
	int result = -ENOMEM;
	int size;
	int res;

	usb_dbg(interface, "probe %s-%s", udev->product, udev->serial);

	/* Find the first bulk IN endpoint and its packet size */
	res = usb_find_bulk_in_endpoint(altsetting, &epd);
	if (res) {
		usb_dbg(interface, "no IN endpoint found");
		return res;
	}

	in_ep = usb_endpoint_num(epd);
	size = usb_endpoint_maxp(epd);

	/* Validate endpoint and size */
	if (size <= 0) {
		usb_dbg(interface, "invalid size (%d)", size);
		return -ENODEV;
	}

	if (size > CHAOSKEY_BUF_LEN) {
		usb_dbg(interface, "size reduced from %d to %d\n",
			size, CHAOSKEY_BUF_LEN);
		size = CHAOSKEY_BUF_LEN;
	}

	/* Looks good, allocate and initialize */

	dev = kzalloc(sizeof(struct chaoskey), GFP_KERNEL);

	if (dev == NULL)
		goto out;

	dev->buf = kmalloc(size, GFP_KERNEL);

	if (dev->buf == NULL)
		goto out;

	dev->urb = usb_alloc_urb(0, GFP_KERNEL);

	if (!dev->urb)
		goto out;

	usb_fill_bulk_urb(dev->urb,
		udev,
		usb_rcvbulkpipe(udev, in_ep),
		dev->buf,
		size,
		chaos_read_callback,
		dev);

	/* Construct a name using the product and serial values. Each
	 * device needs a unique name for the hwrng code
	 */

	if (udev->product && udev->serial) {
		dev->name = kmalloc(strlen(udev->product) + 1 +
				    strlen(udev->serial) + 1, GFP_KERNEL);
		if (dev->name == NULL)
			goto out;

		strcpy(dev->name, udev->product);
		strcat(dev->name, "-");
		strcat(dev->name, udev->serial);
	}

	dev->interface = interface;

	dev->in_ep = in_ep;

	if (le16_to_cpu(udev->descriptor.idVendor) != ALEA_VENDOR_ID)
		dev->reads_started = 1;

	dev->size = size;
	dev->present = 1;

	init_waitqueue_head(&dev->wait_q);

	mutex_init(&dev->lock);
	mutex_init(&dev->rng_lock);

	usb_set_intfdata(interface, dev);

	result = usb_register_dev(interface, &chaoskey_class);
	if (result) {
		usb_err(interface, "Unable to allocate minor number.");
		goto out;
	}

	dev->hwrng.name = dev->name ? dev->name : chaoskey_driver.name;
	dev->hwrng.read = chaoskey_rng_read;
	dev->hwrng.quality = 1024;

	dev->hwrng_registered = (hwrng_register(&dev->hwrng) == 0);
	if (!dev->hwrng_registered)
		usb_err(interface, "Unable to register with hwrng");

	usb_enable_autosuspend(udev);

	usb_dbg(interface, "chaoskey probe success, size %d", dev->size);
	return 0;

out:
	usb_set_intfdata(interface, NULL);
	chaoskey_free(dev);
	return result;
}