コード例 #1
0
ファイル: usblcd.c プロジェクト: liuyang201666/linux-akae
static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
    struct usb_lcd *dev;
    int retval = 0, r;
    struct urb *urb = NULL;
    char *buf = NULL;

    dev = (struct usb_lcd *)file->private_data;

    /* verify that we actually have some data to write */
    if (count == 0)
        goto exit;

    r = down_interruptible(&dev->limit_sem);
    if (r < 0)
        return -EINTR;

    /* create a urb, and a buffer for it, and copy the data to the urb */
    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb) {
        retval = -ENOMEM;
        goto err_no_buf;
    }

    buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
    if (!buf) {
        retval = -ENOMEM;
        goto error;
    }

    if (copy_from_user(buf, user_buffer, count)) {
        retval = -EFAULT;
        goto error;
    }

    /* initialize the urb properly */
    usb_fill_bulk_urb(urb, dev->udev,
                      usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                      buf, count, lcd_write_bulk_callback, dev);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    usb_anchor_urb(urb, &dev->submitted);

    /* send the data out the bulk port */
    retval = usb_submit_urb(urb, GFP_KERNEL);
    if (retval) {
        err("USBLCD: %s - failed submitting write urb, error %d", __func__, retval);
        goto error_unanchor;
    }

    /* release our reference to this urb, the USB core will eventually free it entirely */
    usb_free_urb(urb);

exit:
    return count;
error_unanchor:
    usb_unanchor_urb(urb);
error:
    usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
    usb_free_urb(urb);
err_no_buf:
    up(&dev->limit_sem);
    return retval;
}
コード例 #2
0
ファイル: iowarrior.c プロジェクト: cilynx/dd-wrt
/*
 * iowarrior_write
 */
static ssize_t iowarrior_write(struct file *file,
			       const char __user *user_buffer,
			       size_t count, loff_t *ppos)
{
	struct iowarrior *dev;
	int retval = 0;
	char *buf = NULL;	/* for IOW24 and IOW56 we need a buffer */
	struct urb *int_out_urb = NULL;

	dev = (struct iowarrior *)file->private_data;

	mutex_lock(&dev->mutex);
	/* verify that the device wasn't unplugged */
	if (dev == NULL || !dev->present) {
		retval = -ENODEV;
		goto exit;
	}
	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
	/* if count is 0 we're already done */
	if (count == 0) {
		retval = 0;
		goto exit;
	}
	/* We only accept full reports */
	if (count != dev->report_size) {
		retval = -EINVAL;
		goto exit;
	}
	switch (dev->product_id) {
	case USB_DEVICE_ID_CODEMERCS_IOW24:
	case USB_DEVICE_ID_CODEMERCS_IOWPV1:
	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
	case USB_DEVICE_ID_CODEMERCS_IOW40:
		/* IOW24 and IOW40 use a synchronous call */
		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
		if (!buf) {
			retval = -ENOMEM;
			goto exit;
		}
		if (copy_from_user(buf, user_buffer, count)) {
			retval = -EFAULT;
			kfree(buf);
			goto exit;
		}
		retval = usb_set_report(dev->interface, 2, 0, buf, count);
		kfree(buf);
		goto exit;
		break;
	case USB_DEVICE_ID_CODEMERCS_IOW56:
		/* The IOW56 uses asynchronous IO and more urbs */
		if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
			/* Wait until we are below the limit for submitted urbs */
			if (file->f_flags & O_NONBLOCK) {
				retval = -EAGAIN;
				goto exit;
			} else {
				retval = wait_event_interruptible(dev->write_wait,
								  (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT)));
				if (retval) {
					/* we were interrupted by a signal */
					retval = -ERESTART;
					goto exit;
				}
				if (!dev->present) {
					/* The device was unplugged */
					retval = -ENODEV;
					goto exit;
				}
				if (!dev->opened) {
					/* We were closed while waiting for an URB */
					retval = -ENODEV;
					goto exit;
				}
			}
		}
		atomic_inc(&dev->write_busy);
		int_out_urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!int_out_urb) {
			retval = -ENOMEM;
			dbg("%s Unable to allocate urb ", __func__);
			goto error_no_urb;
		}
		buf = usb_buffer_alloc(dev->udev, dev->report_size,
				       GFP_KERNEL, &int_out_urb->transfer_dma);
		if (!buf) {
			retval = -ENOMEM;
			dbg("%s Unable to allocate buffer ", __func__);
			goto error_no_buffer;
		}
		usb_fill_int_urb(int_out_urb, dev->udev,
				 usb_sndintpipe(dev->udev,
						dev->int_out_endpoint->bEndpointAddress),
				 buf, dev->report_size,
				 iowarrior_write_callback, dev,
				 dev->int_out_endpoint->bInterval);
		int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		if (copy_from_user(buf, user_buffer, count)) {
			retval = -EFAULT;
			goto error;
		}
		retval = usb_submit_urb(int_out_urb, GFP_KERNEL);
		if (retval) {
			dbg("%s submit error %d for urb nr.%d", __func__,
			    retval, atomic_read(&dev->write_busy));
			goto error;
		}
		/* submit was ok */
		retval = count;
		usb_free_urb(int_out_urb);
		goto exit;
		break;
	default:
		/* what do we have here ? An unsupported Product-ID ? */
		dev_err(&dev->interface->dev, "%s - not supported for product=0x%x",
			__FUNCTION__, dev->product_id);
		retval = -EFAULT;
		goto exit;
		break;
	}
error:
	usb_buffer_free(dev->udev, dev->report_size, buf,
			int_out_urb->transfer_dma);
error_no_buffer:
	usb_free_urb(int_out_urb);
error_no_urb:
	atomic_dec(&dev->write_busy);
	wake_up_interruptible(&dev->write_wait);
exit:
	mutex_unlock(&dev->mutex);
	return retval;
}
コード例 #3
0
static int qcnmea_probe (struct usb_interface *intf,
		      const struct usb_device_id *id)
{
    struct usb_device *usb_dev = interface_to_usbdev(intf);
    struct usb_host_interface *cur_intf = intf->cur_altsetting;
    int epnum, minor;
    struct usb_endpoint_descriptor *epread, *epwrite, *eptmp;
    struct qcnmea  *nmea;
    int i, num_rx_buf = QCNMEA_NR;
    
    if(cur_intf->desc.bInterfaceNumber != 1) { /*not the right interface*/
        return -ENODEV;
     }
    printk(KERN_ALERT "this is qct nmea interface!\n");

    epnum = cur_intf->desc.bNumEndpoints;
    if(epnum != 2) {/*endpoint number error*/
	    printk(KERN_ALERT "epnum[%d] is wrong!\n", epnum);
        return -EINVAL;
     }

    while(epnum > 0) {
        eptmp = &cur_intf->endpoint[epnum - 1].desc;
        if(!eptmp) 
            return -EINVAL;
        
        if(usb_endpoint_dir_in(eptmp))
           epread = eptmp;
        else if(usb_endpoint_dir_out(eptmp))
           epwrite = eptmp;

        epnum--;
    }

    if(!epwrite || !epread)
{
        printk(KERN_ALERT "epwrite[%d], epread[%d]\n", epwrite, epread);
        return -EINVAL;
     }

    for(minor = 0; (minor < QC_NMEA_MINORS) && qcnmea_tab[minor]; minor++)   ;

    if(minor == QC_NMEA_MINORS) {
	    printk(KERN_ALERT "minor is wrong!\n");
        return -ENODEV;
    }

    nmea = kzalloc(sizeof(struct qcnmea), GFP_KERNEL);
    if(!nmea) {
	printk(KERN_ALERT "in alloc_fail1\n");
        goto alloc_fail1;
    }

    nmea->usb_dev = usb_dev;
    nmea->read_size = le16_to_cpu(epread->wMaxPacketSize);
    nmea->write_size = le16_to_cpu(epwrite->wMaxPacketSize);
    nmea->intf = intf;
    spin_lock_init(&nmea->throttle_lock);
    spin_lock_init(&nmea->write_lock);
    spin_lock_init(&nmea->read_lock);
    INIT_WORK(&nmea->write_work, qcnmea_write_work, nmea);
    nmea->write_ready = 1;
    nmea->read_pipe = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
    
    if(qcnmea_write_buf_alloc(nmea) < 0) {
	printk(KERN_ALERT "in alloc_fail4\n");
        goto alloc_fail4;
    }

    nmea->write_urb = usb_alloc_urb(0, GFP_KERNEL);
    if(!nmea->write_urb) {
	printk(KERN_ALERT "in alloc_fail5\n");
        goto alloc_fail5;
    }

	for (i = 0; i < num_rx_buf; i++) {
		struct qcnmea_ru *rcv = &(nmea->ru[i]);

		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
			//dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)");
	        printk(KERN_ALERT "in alloc_fail7\n");
			goto alloc_fail7;
		}

		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		rcv->instance = nmea;
	}
	for (i = 0; i < num_rx_buf; i++) {
		struct qcnmea_rb *buf = &(nmea->rb[i]);

		if (!(buf->base = usb_buffer_alloc(nmea->usb_dev, nmea->read_size, GFP_KERNEL, &buf->dma))) {
			//dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)");
	        printk(KERN_ALERT "in alloc_fail7,1\n");
			goto alloc_fail7;
		}
	}

    tasklet_init(&nmea->rx_tasklet, qcnmea_rx_tasklet, nmea);
    usb_set_intfdata(intf, nmea);

    //if(device_create_file(&intf->dev, &dev_attr_bmCapabilities))
	//	goto alloc_fail7;

    usb_fill_bulk_urb(nmea->write_urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
           nmea->write_buf, nmea->write_size, qcnmea_write_bulk, nmea);
    nmea->write_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	nmea->line.dwDTERate = cpu_to_le32(9600);
	nmea->line.bDataBits = 8;
	qcnmea_set_line(nmea, &nmea->line);

    qcnmea_set_control(nmea, nmea->seria_out);

    usb_get_intf(intf);
    tty_register_device(qcnmea_tty_driver, minor, &intf->dev);

    nmea->minor = minor;
    qcnmea_tab[minor] = nmea;

    printk(KERN_ALERT "qct nmea probe ok!, read_size :%d, write_size :%d\n",nmea->read_size, nmea->write_size);

    return 0;

alloc_fail7:
	for (i = 0; i < num_rx_buf; i++)
		usb_buffer_free(usb_dev, nmea->read_size, nmea->rb[i].base, nmea->rb[i].dma);
	for (i = 0; i < num_rx_buf; i++)
		usb_free_urb(nmea->ru[i].urb);
    
alloc_fail6:
    usb_free_urb(nmea->write_urb);
    
alloc_fail5:
    qcnmea_write_buf_free(nmea);

alloc_fail4:
        
alloc_fail3:

alloc_fail2:
    kfree(nmea);
    
alloc_fail1:
コード例 #4
0
ファイル: vote.c プロジェクト: bennyjh/TV2010
//
// IOCTL
//	Control teensy by sending cmd to INTR endpoint
//
//	Currently this function is unused.  We leave it here
//	for possible future use.  (It is replaced by vote_write()).
//
int
vote_ioctl(
    struct inode * i_node,
    struct file * file,
    unsigned int cmd,
    unsigned long arg
) {
    struct usb_vote *vote_dev = file->private_data;
    int err = 0;
    int rc = 0;
    struct urb *vote_urb;	// usb request
    char command;		// g
    char *buf;

    printk(KERN_DEBUG "vote: process %i (%s) vote_ioctl cmd=%d\n",
                          current->pid, current->comm, cmd);

    //
    // Extract the type and number bitfields, and don't decode
    // wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
    //
    if (_IOC_TYPE(cmd) != VOTE_IOCTL_MAGIC) {
	printk(KERN_NOTICE "vote_ioctl: !vote_IOC_MAGIC\n");
	return -ENOTTY;
    }
    if (_IOC_NR(cmd) > VOTE_IOCTL_MAX) {
	printk(KERN_NOTICE "vote_ioctl:  > vote_IOC_MAXNR\n");
	return -ENOTTY;
    }

    //
    // TURNED THIS OFF: If not root/sysadmin, go away
    //
    // if (! capable (CAP_SYS_ADMIN)) return -EPERM;

    //
    // The direction is a bitmask,
    // and VERIFY_WRITE catches R/W transfers.
    // `Type' is user-oriented,
    // while access_ok is kernel-oriented,
    // so the concept of "read" and "write" is reversed.
    //
    if (_IOC_DIR(cmd) & _IOC_READ) {
	err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
    } else if (_IOC_DIR(cmd) & _IOC_WRITE) {
	err = !access_ok(VERIFY_READ,  (void __user *)arg, _IOC_SIZE(cmd));
    }

    if (err) {
	printk(KERN_NOTICE "vote_ioctl: access !ok\n");
	return -EFAULT;
    }

    switch(cmd) {
	case VOTE_IOCTL_INIT:
	    printk(KERN_NOTICE "VOTE_IOCTL_INIT\n");
	    command = 'g';
	    break;
	default:
	    printk(
		KERN_NOTICE "%s: Not a known command: %x\n",
		__FUNCTION__,
		cmd
	    );
	    return -EINVAL;
    } // switch(cmd)

    vote_urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!vote_urb) {
	return -ENOMEM;
    }

    buf = usb_buffer_alloc(
	vote_dev->udev,
	64,
	GFP_KERNEL,
	&vote_urb->transfer_dma
    );
    if (!buf) {
	printk (KERN_NOTICE "%s: usb_buffer_alloc failed\n", __FUNCTION__);
	usb_buffer_free(
	    vote_dev->udev,
	    vote_urb->transfer_buffer_length,
	    vote_urb->transfer_buffer,
	    vote_urb->transfer_dma
	);
	return -ENOMEM;
    }

    buf[0] = command;
    usb_fill_int_urb(
	vote_urb,
	vote_dev->udev,
	usb_sndintpipe(vote_dev->udev, vote_dev->intr_out_endpointAddr),
	buf,
	64,
	(usb_complete_t)vote_write_intr_callback,
	vote_dev,
	250
    );

    vote_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    if ((rc = usb_submit_urb(vote_urb, GFP_KERNEL))) {
	err("%s - failed submitting write urb, error %d", __FUNCTION__, rc);
    }
    return 0;
} // vote_ioctl()
コード例 #5
0
ファイル: vote.c プロジェクト: bennyjh/TV2010
//      read
//
//	wait until the teensy returns data
//
ssize_t
vote_read (struct file *file, char __user *buf, size_t count, loff_t *pos)
{
    struct usb_vote *vote_dev = file->private_data;
    int rc = 0;
    struct urb *vote_urb;	// usb request
    int wqrc = 0;		// return from wait queue
    int bytes_notcopied = 0;
    int copycount = 0;
    int actual_count;
    char *usbbuf;
    char vote_from_teensy;	// single character vote from teensy

    printk(KERN_NOTICE "In %s\n", __FUNCTION__);

    if (!access_ok(VERIFY_WRITE, buf, count))
        return -EINVAL;

    vote_urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!vote_urb) return -ENOMEM;

    usbbuf = usb_buffer_alloc(
	vote_dev->udev,
	64,
	GFP_KERNEL,
	&vote_urb->transfer_dma
    );
    if (!usbbuf) {
	printk (KERN_NOTICE "%s: usb_buffer_alloc failed\n", __FUNCTION__);
	usb_buffer_free(
	    vote_dev->udev,
	    vote_urb->transfer_buffer_length,
	    vote_urb->transfer_buffer,
	    vote_urb->transfer_dma
	);
	return -ENOMEM;
    }

    usb_fill_int_urb(
	vote_urb,
	vote_dev->udev,
	usb_rcvintpipe(vote_dev->udev, vote_dev->intr_in_endpointAddr),
	usbbuf,
	64,
	(usb_complete_t) vote_read_intr_callback,
	vote_dev,
	250
    );

    vote_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    // vote_dev->data_from_teensy = false;
    data_from_teensy = false;


    if ((rc = usb_submit_urb(vote_urb, GFP_KERNEL))) {
	err("%s - failed submitting write urb, error %d", __FUNCTION__, rc);
    }

    //
    // Wait until teensy returns data
    //		We will be awoken by our callback function,
    //		vote_read_intr_callback().
    //
    printk(KERN_DEBUG "%s: process %i (%s) going to sleep\n",
		      __FUNCTION__, current->pid, current->comm);

    wqrc = wait_event_interruptible(
	// vote_dev->wait4voter,
	// vote_dev->data_from_teensy == true
	wait4voter,
	data_from_teensy == true
    );

    if (wqrc ==  -ERESTARTSYS) {
	// Got a signal
	usb_buffer_free(
	    vote_urb->dev,
	    vote_urb->transfer_buffer_length,
	    vote_urb->transfer_buffer,
	    vote_urb->transfer_dma
	);

	printk(KERN_DEBUG "%s got signal while waiting: %i (%s):\n",
    		      __FUNCTION__, current->pid, current->comm);

	// What needs to be deallocated here??? kgb

	return -EINTR;
    }

    printk(KERN_DEBUG "%s awoken %i (%s):\n",
    		      __FUNCTION__, current->pid, current->comm);

    // the actual amount of data from the URB
    actual_count = vote_urb->actual_length;

    printk(KERN_NOTICE "%s: Actual Count in the URB = %d\n",
           __FUNCTION__, actual_count);

    // We are expecting exactly 1 byte from the teensy.
    if (actual_count == 1) {
	vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0];
	// Set the vote in vote_dev->votecast
	// to reflect the voter's choice.
	// This is for viewing in sysfs.
	vote_dev->votecast = vote_from_teensy;
    }

    // actual_count is 64 bytes -- not the amount of data sent from teensy
    // kgb: Since we know its just one byte
    vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0];
    vote_dev->votecast = vote_from_teensy;

    printk(KERN_NOTICE "%s: Vote from teensy. [%c]\n",
           __FUNCTION__, vote_dev->votecast);

    if(count <= actual_count)
        copycount = count;
    else
        copycount = actual_count;

    bytes_notcopied = copy_to_user(
	buf,
	(char *) vote_urb->transfer_buffer,
	copycount
    );

    if (bytes_notcopied != 0) {
	printk(KERN_NOTICE "%s: copy_to_user failed. \n", __FUNCTION__);
    }

    printk(KERN_NOTICE "%s: after copy_to_user. bytes_not_copied=%d \n",
           __FUNCTION__, bytes_notcopied);

    printk(KERN_NOTICE "%s: after copy_to_user. %c\n",
           __FUNCTION__, ((char *) vote_urb->transfer_buffer)[0]);

    // dealloc the URB
    usb_buffer_free(
        vote_urb->dev,
        vote_urb->transfer_buffer_length,
        vote_urb->transfer_buffer,
        vote_urb->transfer_dma
    );


    // return the number of bytes read
    return copycount;

} // vote_read()
コード例 #6
0
ファイル: vote.c プロジェクト: bennyjh/TV2010
ssize_t
vote_write (
    struct file *file,
    const char __user *buf,
    size_t count,
    loff_t *pos)
{
    unsigned long not_copied;   // return from copy_to_user()
    struct urb *wrt_urb;	// usb request: write
    char *tbuf;			// usb transfer buffer
    int rc;

    struct usb_vote *vote_dev = file->private_data;

    printk(KERN_NOTICE "In %s\n", __FUNCTION__);

    if (!access_ok(VERIFY_READ, buf, count)) return -EINVAL;

    if (count > TMAX) {
	printk(KERN_NOTICE "In %s with count=%d > TMAX\n", __FUNCTION__, count);
	return -EINVAL;
    }

    //
    // Set up the urb
    //
    wrt_urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!wrt_urb) return -ENOMEM;

    tbuf = usb_buffer_alloc(
	vote_dev->udev,
	64,
	GFP_KERNEL,
	&wrt_urb->transfer_dma
    );
    if (!tbuf) {
	printk (KERN_NOTICE "%s: usb_buffer_alloc failed\n", __FUNCTION__);
	usb_buffer_free(
	    vote_dev->udev,
	    wrt_urb->transfer_buffer_length,
	    wrt_urb->transfer_buffer,
	    wrt_urb->transfer_dma
	);
	return -ENOMEM;
    }

    // Copy user data to URB transfer buffer
    not_copied = copy_from_user(tbuf,    buf, count);
                             // kernel   user
    if (not_copied != 0) return -EPROTO; // really an internal error

    usb_fill_int_urb(
	wrt_urb,
	vote_dev->udev,
	usb_sndintpipe(vote_dev->udev, vote_dev->intr_out_endpointAddr),
	tbuf,
	64,			// TMAX or count kgb
	(usb_complete_t) vote_write_intr_callback,
	vote_dev,
	250
    );

    wrt_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    if ((rc = usb_submit_urb(wrt_urb, GFP_KERNEL))) {
	err("%s - failed submitting write urb, error %d", __FUNCTION__, rc);
	return rc;
    }

    // Success
    return count;
		
} // vote_write()
コード例 #7
0
ファイル: xpad.c プロジェクト: 325116067/semc-qsd8x50
static void xpad_deinit_output(struct usb_xpad *xpad)
{
	usb_free_urb(xpad->irq_out);
	usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
}
コード例 #8
0
/*
static void ss801u_write_bulk_callback(struct urb *urb)
{
    usb_ss801u *dev;

    dev = (usb_ss801u *)urb->context;

    // sync/async unlink faults aren't errors //
    if (urb->status) {
	if(!(urb->status == -ENOENT ||
	urb->status == -ECONNRESET ||
	urb->status == -ESHUTDOWN))
		err("%s - nonzero write bulk status received: %d",
		__FUNCTION__, urb->status);

		Egis_Reset_device(dev);

		spin_lock(&dev->err_lock);
		dev->errors = urb->status;
		spin_unlock(&dev->err_lock);
	}

    // free up our allocated buffer //
	usb_buffer_free(urb->dev, urb->transfer_buffer_length,
	urb->transfer_buffer, urb->transfer_dma);
	up(&dev->limit_sem);
}
*/
static ssize_t ss801u_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
{
printk(KERN_INFO "Patrick->  ss801u_write start\n");
printk(KERN_INFO "Patrick-> ss801u_write  finish\n");
	//*/
	//--------------- CASE1 : return only -----------------------//
	//-----------------------------------------------------------//
	return -ENOSYS; // function not implement
#if 0
	/*---------------- CASE2 : bulk write -----------------------*/
	/*-----------------------------------------------------------*/
    usb_ss801u *dev;
    int retval = 0;
    struct urb *urb = NULL;
    char *buf = NULL;
    size_t writesize = min(count, (size_t)MAX_TRANSFER);

    dev = (usb_ss801u *)file->private_data;

    if (count == 0)
	goto exit;

	if (down_interruptible(&dev->limit_sem)) {
		retval = -ERESTARTSYS;
		goto exit;
	}

    spin_lock_irq(&dev->err_lock);
	retval = dev->errors;
	if (retval < 0) {
		dev->errors = 0;
		retval = (retval == -EPIPE) ? retval : -EIO;
	}
	spin_unlock_irq(&dev->err_lock);
	if (retval < 0)
		goto error;

    /*----- create a urb, and a buffer for it, and copy the data to the urb -----*/
	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb) {
		retval = -ENOMEM;
		goto error;
	}

	buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
	if (!buf) {
		retval = -ENOMEM;
		goto error;
	}

	if (copy_from_user(buf, user_buffer, writesize)) {
		retval = -EFAULT;
		goto error;
	}

	/*----- this lock makes sure we don't submit URBs to gone devices -----*/
	/*---------------------------------------------------------------------*/
	mutex_lock(&dev->io_mutex);
	if (!dev->interface) {		/* disconnect() was called */
		mutex_unlock(&dev->io_mutex);
		retval = -ENODEV;
		goto error;
	}

	/*----- To NOT go to suspend -----*/
	usb_autopm_get_interface(dev->interface);

	/*----- initialize the urb properly -----*/
	usb_fill_bulk_urb(urb, dev->udev,
	usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
	buf, writesize, ss801u_write_bulk_callback, dev);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
	/*usb_anchor_urb(urb, &dev->submitted);*/

	/*----- send the data out the bulk port -----*/
	retval = usb_submit_urb(urb, GFP_KERNEL);

	/*----- Auto suspend -----*/
	usb_autopm_put_interface(dev->interface);

	mutex_unlock(&dev->io_mutex);
	/*-----------------------------------------------------------*/
	/*-----------------------------------------------------------*/

	if (retval) {
		Egis_Reset_device(dev);
		err("%s - failed submitting write urb, error %d", retval, retval);
		goto error_unanchor;
	}

	/*----- release our reference to this urb, the USB core will eventually free it entirely -----*/
	usb_free_urb(urb);


	return writesize;

error_unanchor:
	usb_unanchor_urb(urb);
error:
	if (urb) {
		usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
		usb_free_urb(urb);
	}
	up(&dev->limit_sem);

exit:
    return retval;
#endif
}
コード例 #9
0
ファイル: usbmouse.c プロジェクト: johnny/CobraDroidBeta
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_mouse *mouse;
	struct input_dev *input_dev;
	int pipe, maxp;
	int error = -ENOMEM;

	interface = intf->cur_altsetting;

	if (interface->desc.bNumEndpoints != 1)
		return -ENODEV;

	endpoint = &interface->endpoint[0].desc;
	if (!usb_endpoint_is_int_in(endpoint))
		return -ENODEV;

	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

	mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!mouse || !input_dev)
		goto fail1;

	mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
	if (!mouse->data)
		goto fail1;

	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!mouse->irq)
		goto fail2;

	mouse->usbdev = dev;
	mouse->dev = input_dev;

	if (dev->manufacturer)
		strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));

	if (dev->product) {
		if (dev->manufacturer)
			strlcat(mouse->name, " ", sizeof(mouse->name));
		strlcat(mouse->name, dev->product, sizeof(mouse->name));
	}

	if (!strlen(mouse->name))
		snprintf(mouse->name, sizeof(mouse->name),
			 "USB HIDBP Mouse %04x:%04x",
			 le16_to_cpu(dev->descriptor.idVendor),
			 le16_to_cpu(dev->descriptor.idProduct));

	usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
	strlcat(mouse->phys, "/input0", sizeof(mouse->phys));

	input_dev->name = mouse->name;
	input_dev->phys = mouse->phys;
	usb_to_input_id(dev, &input_dev->id);
	input_dev->dev.parent = &intf->dev;

	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
	input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
	input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
	input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
		BIT_MASK(BTN_EXTRA);
	input_dev->relbit[0] |= BIT_MASK(REL_WHEEL);

	input_set_drvdata(input_dev, mouse);

	input_dev->open = usb_mouse_open;
	input_dev->close = usb_mouse_close;

	usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
			 (maxp > 8 ? 8 : maxp),
			 usb_mouse_irq, mouse, endpoint->bInterval);
	mouse->irq->transfer_dma = mouse->data_dma;
	mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	error = input_register_device(mouse->dev);
	if (error)
		goto fail3;

	usb_set_intfdata(intf, mouse);
	return 0;

fail3:	
	usb_free_urb(mouse->irq);
fail2:	
	usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
fail1:	
	input_free_device(input_dev);
	kfree(mouse);
	return error;
}
コード例 #10
0
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_endpoint_descriptor *endpoint;
	struct wacom *wacom;
	struct wacom_wac *wacom_wac;
	struct wacom_features *features;
	struct input_dev *input_dev;
	int error;

	if (!id->driver_info)
		return -EINVAL;

	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
	wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!wacom || !input_dev || !wacom_wac) {
		error = -ENOMEM;
		goto fail1;
	}

	wacom_wac->features = *((struct wacom_features *)id->driver_info);
	features = &wacom_wac->features;
	if (features->pktlen > WACOM_PKGLEN_MAX) {
		error = -EINVAL;
		goto fail1;
	}

	wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX,
					   GFP_KERNEL, &wacom->data_dma);
	if (!wacom_wac->data) {
		error = -ENOMEM;
		goto fail1;
	}

	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!wacom->irq) {
		error = -ENOMEM;
		goto fail2;
	}

	wacom->usbdev = dev;
	wacom->dev = input_dev;
	wacom->intf = intf;
	mutex_init(&wacom->lock);
	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));

	usb_to_input_id(dev, &input_dev->id);

	input_dev->dev.parent = &intf->dev;

	input_set_drvdata(input_dev, wacom);

	input_dev->open = wacom_open;
	input_dev->close = wacom_close;

	endpoint = &intf->cur_altsetting->endpoint[0].desc;

	/* Retrieve the physical and logical size for OEM devices */
	error = wacom_retrieve_hid_descriptor(intf, features);
	if (error)
		goto fail2;

	strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));

	if (features->type == TABLETPC || features->type == TABLETPC2FG) {
		/* Append the device type to the name */
		strlcat(wacom_wac->name,
			features->device_type == BTN_TOOL_PEN ?
				" Pen" : " Finger",
			sizeof(wacom_wac->name));
	}

	input_dev->name = wacom_wac->name;
	wacom->wacom_wac = wacom_wac;

	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH);

	input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
	input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);

	wacom_init_input_dev(input_dev, wacom_wac);

	usb_fill_int_urb(wacom->irq, dev,
			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
			 wacom_wac->data, features->pktlen,
			 wacom_sys_irq, wacom, endpoint->bInterval);
	wacom->irq->transfer_dma = wacom->data_dma;
	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	error = input_register_device(wacom->dev);
	if (error)
		goto fail3;

	/* Note that if query fails it is not a hard failure */
	wacom_query_tablet_data(intf, features);

	usb_set_intfdata(intf, wacom);
	return 0;

 fail3:	usb_free_urb(wacom->irq);
 fail2:	usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
 fail1:	input_free_device(input_dev);
	kfree(wacom);
	kfree(wacom_wac);
	return error;
}
コード例 #11
0
ファイル: onetouch.c プロジェクト: 3sOx/asuswrt-merlin
int onetouch_connect_input(struct us_data *ss)
{
	struct usb_device *udev = ss->pusb_dev;
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_onetouch *onetouch;
	struct input_dev *input_dev;
	int pipe, maxp;
	int error = -ENOMEM;

	interface = ss->pusb_intf->cur_altsetting;

	if (interface->desc.bNumEndpoints != 3)
		return -ENODEV;

	endpoint = &interface->endpoint[2].desc;
	if (!usb_endpoint_is_int_in(endpoint))
		return -ENODEV;

	pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));

	onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!onetouch || !input_dev)
		goto fail1;

	onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
					  GFP_ATOMIC, &onetouch->data_dma);
	if (!onetouch->data)
		goto fail1;

	onetouch->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!onetouch->irq)
		goto fail2;

	onetouch->udev = udev;
	onetouch->dev = input_dev;

	if (udev->manufacturer)
		strlcpy(onetouch->name, udev->manufacturer,
			sizeof(onetouch->name));
	if (udev->product) {
		if (udev->manufacturer)
			strlcat(onetouch->name, " ", sizeof(onetouch->name));
		strlcat(onetouch->name, udev->product, sizeof(onetouch->name));
	}

	if (!strlen(onetouch->name))
		snprintf(onetouch->name, sizeof(onetouch->name),
			 "Maxtor Onetouch %04x:%04x",
			 le16_to_cpu(udev->descriptor.idVendor),
			 le16_to_cpu(udev->descriptor.idProduct));

	usb_make_path(udev, onetouch->phys, sizeof(onetouch->phys));
	strlcat(onetouch->phys, "/input0", sizeof(onetouch->phys));

	input_dev->name = onetouch->name;
	input_dev->phys = onetouch->phys;
	usb_to_input_id(udev, &input_dev->id);
	input_dev->dev.parent = &udev->dev;

	set_bit(EV_KEY, input_dev->evbit);
	set_bit(ONETOUCH_BUTTON, input_dev->keybit);
	clear_bit(0, input_dev->keybit);

	input_set_drvdata(input_dev, onetouch);

	input_dev->open = usb_onetouch_open;
	input_dev->close = usb_onetouch_close;

	usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
			 (maxp > 8 ? 8 : maxp),
			 usb_onetouch_irq, onetouch, endpoint->bInterval);
	onetouch->irq->transfer_dma = onetouch->data_dma;
	onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	ss->extra_destructor = onetouch_release_input;
	ss->extra = onetouch;
#ifdef CONFIG_PM
	ss->suspend_resume_hook = usb_onetouch_pm_hook;
#endif

	error = input_register_device(onetouch->dev);
	if (error)
		goto fail3;

	return 0;

 fail3:	usb_free_urb(onetouch->irq);
 fail2:	usb_buffer_free(udev, ONETOUCH_PKT_LEN,
			onetouch->data, onetouch->data_dma);
 fail1:	kfree(onetouch);
	input_free_device(input_dev);
	return error;
}
コード例 #12
0
ファイル: wacom_sys.c プロジェクト: acassis/emlinux-ssd1935
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_endpoint_descriptor *endpoint;
    struct wacom *wacom;
    struct wacom_wac *wacom_wac;
    struct input_dev *input_dev;
    int error = -ENOMEM;
    char rep_data[2], limit = 0;

    wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
    wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
    input_dev = input_allocate_device();
    if (!wacom || !input_dev || !wacom_wac)
        goto fail1;

    wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
    if (!wacom_wac->data)
        goto fail1;

    wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
    if (!wacom->irq)
        goto fail2;

    wacom->usbdev = dev;
    wacom->dev = input_dev;
    usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
    strlcat(wacom->phys, "/input0", sizeof(wacom->phys));

    wacom_wac->features = get_wacom_feature(id);
    BUG_ON(wacom_wac->features->pktlen > 10);

    input_dev->name = wacom_wac->features->name;
    wacom->wacom_wac = wacom_wac;
    usb_to_input_id(dev, &input_dev->id);

    input_dev->dev.parent = &intf->dev;

    input_set_drvdata(input_dev, wacom);

    input_dev->open = wacom_open;
    input_dev->close = wacom_close;

    input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
            BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
    input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
    input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
    input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
    input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);

    wacom_init_input_dev(input_dev, wacom_wac);

    endpoint = &intf->cur_altsetting->endpoint[0].desc;

    usb_fill_int_urb(wacom->irq, dev,
                     usb_rcvintpipe(dev, endpoint->bEndpointAddress),
                     wacom_wac->data, wacom_wac->features->pktlen,
                     wacom_sys_irq, wacom, endpoint->bInterval);
    wacom->irq->transfer_dma = wacom->data_dma;
    wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    error = input_register_device(wacom->dev);
    if (error)
        goto fail3;

    /* Ask the tablet to report tablet data. Repeat until it succeeds */
    do {
        rep_data[0] = 2;
        rep_data[1] = 2;
        usb_set_report(intf, 3, 2, rep_data, 2);
        usb_get_report(intf, 3, 2, rep_data, 2);
    } while (rep_data[1] != 2 && limit++ < 5);

    usb_set_intfdata(intf, wacom);
    return 0;

fail3:
    usb_free_urb(wacom->irq);
fail2:
    usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
fail1:
    input_free_device(input_dev);
    kfree(wacom);
    kfree(wacom_wac);
    return error;
}
コード例 #13
0
static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	int rv = -EINVAL;
	struct usb_device *udev = interface_to_usbdev(intf);
	struct wdm_device *desc;
	struct usb_host_interface *iface;
	struct usb_endpoint_descriptor *ep;
	struct usb_cdc_dmm_desc *dmhd;
	u8 *buffer = intf->altsetting->extra;
	int buflen = intf->altsetting->extralen;
	u16 maxcom = 0;

	if (!buffer)
		goto out;

	while (buflen > 2) {
		if (buffer [1] != USB_DT_CS_INTERFACE) {
			dev_err(&intf->dev, "skipping garbage\n");
			goto next_desc;
		}

		switch (buffer [2]) {
		case USB_CDC_HEADER_TYPE:
			break;
		case USB_CDC_DMM_TYPE:
			dmhd = (struct usb_cdc_dmm_desc *)buffer;
			maxcom = le16_to_cpu(dmhd->wMaxCommand);
			dev_dbg(&intf->dev,
				"Finding maximum buffer length: %d", maxcom);
			break;
		default:
			dev_err(&intf->dev,
				"Ignoring extra header, type %d, length %d\n",
				buffer[2], buffer[0]);
			break;
		}
next_desc:
		buflen -= buffer[0];
		buffer += buffer[0];
	}

	rv = -ENOMEM;
	desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
	if (!desc)
		goto out;
	mutex_init(&desc->wlock);
	mutex_init(&desc->rlock);
	mutex_init(&desc->plock);
	spin_lock_init(&desc->iuspin);
	init_waitqueue_head(&desc->wait);
	desc->wMaxCommand = maxcom;
	/* this will be expanded and needed in hardware endianness */
	desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
	desc->intf = intf;
	INIT_WORK(&desc->rxwork, wdm_rxwork);

	rv = -EINVAL;
	iface = intf->cur_altsetting;
	if (iface->desc.bNumEndpoints != 1)
		goto err;
	ep = &iface->endpoint[0].desc;
	if (!ep || !usb_endpoint_is_int_in(ep))
		goto err;

	desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
	desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;

	desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
	if (!desc->orq)
		goto err;
	desc->irq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
	if (!desc->irq)
		goto err;

	desc->validity = usb_alloc_urb(0, GFP_KERNEL);
	if (!desc->validity)
		goto err;

	desc->response = usb_alloc_urb(0, GFP_KERNEL);
	if (!desc->response)
		goto err;

	desc->command = usb_alloc_urb(0, GFP_KERNEL);
	if (!desc->command)
		goto err;

	desc->ubuf = kmalloc(desc->wMaxCommand, GFP_KERNEL);
	if (!desc->ubuf)
		goto err;

	desc->sbuf = usb_buffer_alloc(interface_to_usbdev(intf),
					desc->wMaxPacketSize,
					GFP_KERNEL,
					&desc->validity->transfer_dma);
	if (!desc->sbuf)
		goto err;

	desc->inbuf = usb_buffer_alloc(interface_to_usbdev(intf),
					desc->bMaxPacketSize0,
					GFP_KERNEL,
					&desc->response->transfer_dma);
	if (!desc->inbuf)
		goto err2;

	usb_fill_int_urb(
		desc->validity,
		interface_to_usbdev(intf),
		usb_rcvintpipe(interface_to_usbdev(intf), ep->bEndpointAddress),
		desc->sbuf,
		desc->wMaxPacketSize,
		wdm_int_callback,
		desc,
		ep->bInterval
	);
	desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	usb_set_intfdata(intf, desc);
	rv = usb_register_dev(intf, &wdm_class);
	if (rv < 0)
		goto err3;
	else
		dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
			intf->minor - WDM_MINOR_BASE);
out:
	return rv;
err3:
	usb_set_intfdata(intf, NULL);
	usb_buffer_free(interface_to_usbdev(desc->intf),
			desc->bMaxPacketSize0,
			desc->inbuf,
			desc->response->transfer_dma);
err2:
	usb_buffer_free(interface_to_usbdev(desc->intf),
			desc->wMaxPacketSize,
			desc->sbuf,
			desc->validity->transfer_dma);
err:
	free_urbs(desc);
	kfree(desc->ubuf);
	kfree(desc->orq);
	kfree(desc->irq);
	kfree(desc);
	return rv;
}
コード例 #14
0
ファイル: cdc-acm.c プロジェクト: PennPanda/linux-repo
static int acm_probe (struct usb_interface *intf,
		      const struct usb_device_id *id)
{
	struct usb_cdc_union_desc *union_header = NULL;
	struct usb_cdc_country_functional_desc *cfd = NULL;
	char *buffer = intf->altsetting->extra;
	int buflen = intf->altsetting->extralen;
	struct usb_interface *control_interface;
	struct usb_interface *data_interface;
	struct usb_endpoint_descriptor *epctrl;
	struct usb_endpoint_descriptor *epread;
	struct usb_endpoint_descriptor *epwrite;
	struct usb_device *usb_dev = interface_to_usbdev(intf);
	struct acm *acm;
	int minor;
	int ctrlsize,readsize;
	u8 *buf;
	u8 ac_management_function = 0;
	u8 call_management_function = 0;
	int call_interface_num = -1;
	int data_interface_num;
	unsigned long quirks;
	int num_rx_buf;
	int i;

	/* normal quirks */
	quirks = (unsigned long)id->driver_info;
	num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;

	/* handle quirks deadly to normal probing*/
	if (quirks == NO_UNION_NORMAL) {
		data_interface = usb_ifnum_to_if(usb_dev, 1);
		control_interface = usb_ifnum_to_if(usb_dev, 0);
		goto skip_normal_probe;
	}
	
	/* normal probing*/
	if (!buffer) {
		err("Weird descriptor references\n");
		return -EINVAL;
	}

	if (!buflen) {
		if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
			dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n");
			buflen = intf->cur_altsetting->endpoint->extralen;
			buffer = intf->cur_altsetting->endpoint->extra;
		} else {
			err("Zero length descriptor references\n");
			return -EINVAL;
		}
	}

	while (buflen > 0) {
		if (buffer [1] != USB_DT_CS_INTERFACE) {
			err("skipping garbage\n");
			goto next_desc;
		}

		switch (buffer [2]) {
			case USB_CDC_UNION_TYPE: /* we've found it */
				if (union_header) {
					err("More than one union descriptor, skipping ...");
					goto next_desc;
				}
				union_header = (struct usb_cdc_union_desc *)
							buffer;
				break;
			case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
				cfd = (struct usb_cdc_country_functional_desc *)buffer;
				break;
			case USB_CDC_HEADER_TYPE: /* maybe check version */ 
				break; /* for now we ignore it */ 
			case USB_CDC_ACM_TYPE:
				ac_management_function = buffer[3];
				break;
			case USB_CDC_CALL_MANAGEMENT_TYPE:
				call_management_function = buffer[3];
				call_interface_num = buffer[4];
				if ((call_management_function & 3) != 3)
					err("This device cannot do calls on its own. It is no modem.");
				break;
				
			default:
				err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
				break;
			}
next_desc:
		buflen -= buffer[0];
		buffer += buffer[0];
	}

	if (!union_header) {
		if (call_interface_num > 0) {
			dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
			control_interface = intf;
		} else {
			dev_dbg(&intf->dev,"No union descriptor, giving up\n");
			return -ENODEV;
		}
	} else {
		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
		data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
		if (!control_interface || !data_interface) {
			dev_dbg(&intf->dev,"no interfaces\n");
			return -ENODEV;
		}
	}
	
	if (data_interface_num != call_interface_num)
		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.\n");

skip_normal_probe:

	/*workaround for switched interfaces */
	if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) {
		if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) {
			struct usb_interface *t;
			dev_dbg(&intf->dev,"Your device has switched interfaces.\n");

			t = control_interface;
			control_interface = data_interface;
			data_interface = t;
		} else {
			return -EINVAL;
		}
	}

	/* Accept probe requests only for the control interface */
	if (intf != control_interface)
		return -ENODEV;
	
	if (usb_interface_claimed(data_interface)) { /* valid in this context */
		dev_dbg(&intf->dev,"The data interface isn't available\n");
		return -EBUSY;
	}


	if (data_interface->cur_altsetting->desc.bNumEndpoints < 2)
		return -EINVAL;

	epctrl = &control_interface->cur_altsetting->endpoint[0].desc;
	epread = &data_interface->cur_altsetting->endpoint[0].desc;
	epwrite = &data_interface->cur_altsetting->endpoint[1].desc;


	/* workaround for switched endpoints */
	if (!usb_endpoint_dir_in(epread)) {
		/* descriptors are swapped */
		struct usb_endpoint_descriptor *t;
		dev_dbg(&intf->dev,"The data interface has switched endpoints\n");
		
		t = epread;
		epread = epwrite;
		epwrite = t;
	}
	dbg("interfaces are valid");
	for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);

	if (minor == ACM_TTY_MINORS) {
		err("no more free acm devices");
		return -ENODEV;
	}

	if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) {
		dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n");
		goto alloc_fail;
	}

	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
	readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
	acm->control = control_interface;
	acm->data = data_interface;
	acm->minor = minor;
	acm->dev = usb_dev;
	acm->ctrl_caps = ac_management_function;
	acm->ctrlsize = ctrlsize;
	acm->readsize = readsize;
	acm->rx_buflimit = num_rx_buf;
	acm->urb_task.func = acm_rx_tasklet;
	acm->urb_task.data = (unsigned long) acm;
	INIT_WORK(&acm->work, acm_softint);
	spin_lock_init(&acm->throttle_lock);
	spin_lock_init(&acm->write_lock);
	spin_lock_init(&acm->read_lock);
	acm->write_ready = 1;
	acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);

	buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
	if (!buf) {
		dev_dbg(&intf->dev, "out of memory (ctrl buffer alloc)\n");
		goto alloc_fail2;
	}
	acm->ctrl_buffer = buf;

	if (acm_write_buffers_alloc(acm) < 0) {
		dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
		goto alloc_fail4;
	}

	acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL);
	if (!acm->ctrlurb) {
		dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
		goto alloc_fail5;
	}
	for (i = 0; i < num_rx_buf; i++) {
		struct acm_ru *rcv = &(acm->ru[i]);

		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
			dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
			goto alloc_fail7;
		}

		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		rcv->instance = acm;
	}
	for (i = 0; i < num_rx_buf; i++) {
		struct acm_rb *buf = &(acm->rb[i]);

		if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
			dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
			goto alloc_fail7;
		}
	}
	acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
	if (!acm->writeurb) {
		dev_dbg(&intf->dev, "out of memory (writeurb kmalloc)\n");
		goto alloc_fail7;
	}

	usb_set_intfdata (intf, acm);

	i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
	if (i < 0)
		goto alloc_fail8;

	if (cfd) { /* export the country data */
		acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
		if (!acm->country_codes)
			goto skip_countries;
		acm->country_code_size = cfd->bLength - 4;
		memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4);
		acm->country_rel_date = cfd->iCountryCodeRelDate;

		i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
		if (i < 0) {
			kfree(acm->country_codes);
			goto skip_countries;
		}

		i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
		if (i < 0) {
			kfree(acm->country_codes);
			goto skip_countries;
		}
	}

skip_countries:
	usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress),
			 acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
	acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
	acm->ctrlurb->transfer_dma = acm->ctrl_dma;

	usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
			  NULL, acm->writesize, acm_write_bulk, acm);
	acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;

	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);

	acm_set_control(acm, acm->ctrlout);

	acm->line.dwDTERate = cpu_to_le32(9600);
	acm->line.bDataBits = 8;
	acm_set_line(acm, &acm->line);

	usb_driver_claim_interface(&acm_driver, data_interface, acm);

	usb_get_intf(control_interface);
	tty_register_device(acm_tty_driver, minor, &control_interface->dev);

	acm_table[minor] = acm;

	return 0;
alloc_fail8:
	usb_free_urb(acm->writeurb);
alloc_fail7:
	for (i = 0; i < num_rx_buf; i++)
		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
	for (i = 0; i < num_rx_buf; i++)
		usb_free_urb(acm->ru[i].urb);
	usb_free_urb(acm->ctrlurb);
alloc_fail5:
	acm_write_buffers_free(acm);
alloc_fail4:
	usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail2:
	kfree(acm);
alloc_fail:
	return -ENOMEM;
}
コード例 #15
0
static int appledisplay_probe(struct usb_interface *iface,
	const struct usb_device_id *id)
{
	struct backlight_properties props;
	struct appledisplay *pdata;
	struct usb_device *udev = interface_to_usbdev(iface);
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	int int_in_endpointAddr = 0;
	int i, retval = -ENOMEM, brightness;
	char bl_name[20];

	/* set up the endpoint information */
	/* use only the first interrupt-in endpoint */
	iface_desc = iface->cur_altsetting;
	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
		endpoint = &iface_desc->endpoint[i].desc;
		if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
			/* we found an interrupt in endpoint */
			int_in_endpointAddr = endpoint->bEndpointAddress;
			break;
		}
	}
	if (!int_in_endpointAddr) {
		dev_err(&iface->dev, "Could not find int-in endpoint\n");
		return -EIO;
	}

	/* allocate memory for our device state and initialize it */
	pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL);
	if (!pdata) {
		retval = -ENOMEM;
		dev_err(&iface->dev, "Out of memory\n");
		goto error;
	}

	pdata->udev = udev;

	spin_lock_init(&pdata->lock);
	INIT_DELAYED_WORK(&pdata->work, appledisplay_work);

	/* Allocate buffer for control messages */
	pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
	if (!pdata->msgdata) {
		retval = -ENOMEM;
		dev_err(&iface->dev,
			"Allocating buffer for control messages failed\n");
		goto error;
	}

	/* Allocate interrupt URB */
	pdata->urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!pdata->urb) {
		retval = -ENOMEM;
		dev_err(&iface->dev, "Allocating URB failed\n");
		goto error;
	}

	/* Allocate buffer for interrupt data */
	pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN,
		GFP_KERNEL, &pdata->urb->transfer_dma);
	if (!pdata->urbdata) {
		retval = -ENOMEM;
		dev_err(&iface->dev, "Allocating URB buffer failed\n");
		goto error;
	}

	/* Configure interrupt URB */
	usb_fill_int_urb(pdata->urb, udev,
		usb_rcvintpipe(udev, int_in_endpointAddr),
		pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete,
		pdata, 1);
	if (usb_submit_urb(pdata->urb, GFP_KERNEL)) {
		retval = -EIO;
		dev_err(&iface->dev, "Submitting URB failed\n");
		goto error;
	}

	/* Register backlight device */
	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
		atomic_inc_return(&count_displays) - 1);
	memset(&props, 0, sizeof(struct backlight_properties));
	props.max_brightness = 0xff;
	pdata->bd = backlight_device_register(bl_name, NULL, pdata,
					      &appledisplay_bl_data, &props);
	if (IS_ERR(pdata->bd)) {
		dev_err(&iface->dev, "Backlight registration failed\n");
		retval = PTR_ERR(pdata->bd);
		goto error;
	}

	/* Try to get brightness */
	brightness = appledisplay_bl_get_brightness(pdata->bd);

	if (brightness < 0) {
		retval = brightness;
		dev_err(&iface->dev,
			"Error while getting initial brightness: %d\n", retval);
		goto error;
	}

	/* Set brightness in backlight device */
	pdata->bd->props.brightness = brightness;

	/* save our data pointer in the interface device */
	usb_set_intfdata(iface, pdata);

	printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n");

	return 0;

error:
	if (pdata) {
		if (pdata->urb) {
			usb_kill_urb(pdata->urb);
			if (pdata->urbdata)
				usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN,
					pdata->urbdata, pdata->urb->transfer_dma);
			usb_free_urb(pdata->urb);
		}
		if (pdata->bd && !IS_ERR(pdata->bd))
			backlight_device_unregister(pdata->bd);
		kfree(pdata->msgdata);
	}
	usb_set_intfdata(iface, NULL);
	kfree(pdata);
	return retval;
}
コード例 #16
0
/*
 * probe function for new CPC-USB devices
 */
static int cpcusb_probe(struct usb_interface *interface,
			const struct usb_device_id *id)
{
	CPC_USB_T *card = NULL;
	CPC_CHAN_T *chan = NULL;

	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;

	int i, j, retval = -ENOMEM, slot;

	slot = cpcusb_get_free_slot();
	if (slot < 0) {
		info("No more devices supported");
		return -ENOMEM;
	}

	/* allocate memory for our device state and initialize it */
	card = kzalloc(sizeof(CPC_USB_T), GFP_KERNEL);
	if (!card) {
		err("Out of memory");
		return -ENOMEM;
	}
	CPCUSB_Table[slot] = card;

	/* allocate and initialize the channel struct */
	card->chan = kmalloc(sizeof(CPC_CHAN_T), GFP_KERNEL);
	if (!card->chan) {
		kfree(card);
		err("Out of memory");
		return -ENOMEM;
	}

	chan = card->chan;
	memset(chan, 0, sizeof(CPC_CHAN_T));
	ResetBuffer(chan);

	semaphore_init(&card->sem);
	spin_lock_init(&card->slock);

	card->udev = udev;
	card->interface = interface;
	if (udev->descriptor.iSerialNumber) {
		usb_string(udev, udev->descriptor.iSerialNumber, card->serialNumber,
				   128);
		info("Serial %s", card->serialNumber);
	}

	card->productId = udev->descriptor.idProduct;
	info("Product %s",
	     card->productId == USB_CPCUSB_LPC2119_PRODUCT_ID ?
			 "CPC-USB/ARM7" : "CPC-USB/M16C");

	/* set up the endpoint information */
	/* check out the endpoints */
	/* use only the first bulk-in and bulk-out endpoints */
	iface_desc = &interface->altsetting[0];
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
		endpoint = &iface_desc->endpoint[i].desc;

		if (!card->num_intr_in &&
		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
		     == USB_ENDPOINT_XFER_INT)) {
			card->intr_in_urb = usb_alloc_urb(0, GFP_KERNEL);
			card->num_intr_in = 1;

			if (!card->intr_in_urb) {
				err("No free urbs available");
				goto error;
			}

			dbg("intr_in urb %d", card->num_intr_in);
		}

		if (!card->num_bulk_in &&
		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
		     == USB_ENDPOINT_XFER_BULK)) {
			card->num_bulk_in = 2;
			for (j = 0; j < CPC_USB_URB_CNT; j++) {
				card->urbs[j].size = endpoint->wMaxPacketSize;
				card->urbs[j].urb = usb_alloc_urb(0, GFP_KERNEL);
				if (!card->urbs[j].urb) {
					err("No free urbs available");
					goto error;
				}
				card->urbs[j].buffer =
				    usb_buffer_alloc(udev,
						     card->urbs[j].size,
						     GFP_KERNEL,
						     &card->urbs[j].urb->transfer_dma);
				if (!card->urbs[j].buffer) {
					err("Couldn't allocate bulk_in_buffer");
					goto error;
				}
			}
			info("%s - %d reading URB's allocated",
			     __func__, CPC_USB_URB_CNT);
		}

		if (!card->num_bulk_out &&
		    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
		     == USB_ENDPOINT_XFER_BULK)) {

			card->num_bulk_out = 2;

			for (j = 0; j < CPC_USB_URB_CNT; j++) {
				card->wrUrbs[j].size =
				    endpoint->wMaxPacketSize;
				card->wrUrbs[j].urb =
				    usb_alloc_urb(0, GFP_KERNEL);
				if (!card->wrUrbs[j].urb) {
					err("No free urbs available");
					goto error;
				}
				card->wrUrbs[j].buffer = usb_buffer_alloc(udev,
							       card->wrUrbs[j].size, GFP_KERNEL,
							       &card->wrUrbs[j].urb->transfer_dma);

				if (!card->wrUrbs[j].buffer) {
					err("Couldn't allocate bulk_out_buffer");
					goto error;
				}

				usb_fill_bulk_urb(card->wrUrbs[j].urb, udev,
						usb_sndbulkpipe(udev, endpoint->bEndpointAddress),
						card->wrUrbs[j].buffer,
						card->wrUrbs[j].size,
						cpcusb_write_bulk_callback,
						card);
			}

			info("%s - %d writing URB's allocated", __func__, CPC_USB_URB_CNT);
		}
	}

	if (!(card->num_bulk_in && card->num_bulk_out)) {
		err("Couldn't find both bulk-in and bulk-out endpoints");
		goto error;
	}

	/* allow device read, write and ioctl */
	card->present = 1;

	/* we can register the device now, as it is ready */
	usb_set_intfdata(interface, card);
	retval = usb_register_dev(interface, &cpcusb_class);

	if (retval) {
		/* something prevented us from registering this driver */
		err("Not able to get a minor for this device.");
		usb_set_intfdata(interface, NULL);
		goto error;
	}

	card->chan->minor = card->minor = interface->minor;

	chan->buf = vmalloc(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);
	if (chan->buf == NULL) {
		err("Out of memory");
		retval = -ENOMEM;
		goto error;
	}
	info("Allocated memory for %d messages (%lu kbytes)",
	     CPC_MSG_BUF_CNT, (long unsigned int)(sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT) / 1000);
	memset(chan->buf, 0, sizeof(CPC_MSG_T) * CPC_MSG_BUF_CNT);

	ResetBuffer(chan);

	card->chan->CPCWait_q = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
	if (!card->chan->CPCWait_q) {
		err("Out of memory");
		retval = -ENOMEM;
		goto error;
	}
	init_waitqueue_head(card->chan->CPCWait_q);

	CPCUSB_Table[slot] = card;
	card->idx = slot;
	CPCUsbCnt++;

	/* let the user know what node this device is now attached to */
	info("Device now attached to USB-%d", card->minor);
	return 0;

error:
	for (j = 0; j < CPC_USB_URB_CNT; j++) {
		if (card->urbs[j].buffer) {
			usb_buffer_free(card->udev, card->urbs[j].size,
					card->urbs[j].buffer,
					card->urbs[j].urb->transfer_dma);
			card->urbs[j].buffer = NULL;
		}
		if (card->urbs[j].urb) {
			usb_free_urb(card->urbs[j].urb);
			card->urbs[j].urb = NULL;
		}
	}

	cpcusb_delete(card);
	return retval;
}
コード例 #17
0
ファイル: InterfaceTx.c プロジェクト: 3sOx/asuswrt-merlin
/*this is transmit call-back(BULK OUT)*/
static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/)
{
	PUSB_TCB pTcb= (PUSB_TCB)urb->context;
	PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter;
	CONTROL_MESSAGE *pControlMsg = (CONTROL_MESSAGE *)urb->transfer_buffer; 
	PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ;
	BOOLEAN bpowerDownMsg = FALSE ;
    PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
#if 0	
	struct timeval tv;
	UINT time_ms = 0;
#endif
	if(urb->status != STATUS_SUCCESS)
	{
		if(urb->status == -EPIPE)
		{
			psIntfAdapter->psAdapter->bEndPointHalted = TRUE ;
			wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue);
		}
		else
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Tx URB has got cancelled. status :%d", urb->status);
		}
	}

	pTcb->bUsed = FALSE;
	atomic_dec(&psIntfAdapter->uNumTcbUsed);
	
	

	if(TRUE == psAdapter->bPreparingForLowPowerMode) 
	{
		#if 0
		do_gettimeofday(&tv);
		time_ms = tv.tv_sec *1000 + tv.tv_usec/1000;
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " %s Idle Mode ACK_Sent got from device at time :0x%x", __FUNCTION__, time_ms);	
		#endif
		
		if(((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) &&
			(pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)))

		{
			bpowerDownMsg = TRUE ;
			//This covers the bus err while Idle Request msg sent down.
			if(urb->status != STATUS_SUCCESS)
			{
				psAdapter->bPreparingForLowPowerMode = FALSE ;
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Idle Mode Request msg failed to reach to Modem");
				//Signalling the cntrl pkt path in Ioctl
				wake_up(&psAdapter->lowpower_mode_wait_queue);
				StartInterruptUrb(psIntfAdapter);
				goto err_exit;
			}
			
			if(psAdapter->bDoSuspend == FALSE)
			{
				psAdapter->IdleMode = TRUE;
				//since going in Idle mode completed hence making this var false;
				psAdapter->bPreparingForLowPowerMode = FALSE ;

				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
				//Signalling the cntrl pkt path in Ioctl
				wake_up(&psAdapter->lowpower_mode_wait_queue);
			}
				
		}
		else if((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) &&
			(pControlMsg->szData[0] == LINK_UP_ACK) &&
			(pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE)  &&
			(pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER))
		{
			//This covers the bus err while shutdown Request msg sent down.
			if(urb->status != STATUS_SUCCESS)
			{
				psAdapter->bPreparingForLowPowerMode = FALSE ;
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Shutdown Request Msg failed to reach to Modem");
				//Signalling the cntrl pkt path in Ioctl
				wake_up(&psAdapter->lowpower_mode_wait_queue);
				StartInterruptUrb(psIntfAdapter);
				goto err_exit;
			}
			
			bpowerDownMsg = TRUE ;
			if(psAdapter->bDoSuspend == FALSE)
			{
				psAdapter->bShutStatus = TRUE;
				//since going in shutdown mode completed hence making this var false;
				psAdapter->bPreparingForLowPowerMode = FALSE ;
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Host Entered in shutdown Mode State...");
				//Signalling the cntrl pkt path in Ioctl
				wake_up(&psAdapter->lowpower_mode_wait_queue);
			}		
		}

		if(psAdapter->bDoSuspend && bpowerDownMsg)
		{
			//issuing bus suspend request 
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Issuing the Bus suspend request to USB stack");
			psIntfAdapter->bPreparingForBusSuspend = TRUE;
			schedule_work(&psIntfAdapter->usbSuspendWork);
			
		}
				
	}
	
err_exit :
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
	usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma);
#else
	usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma);
#endif
}
コード例 #18
0
ファイル: xpad.c プロジェクト: 3sOx/asuswrt-merlin
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev (intf);
	struct usb_xpad *xpad;
	struct input_dev *input_dev;
	struct usb_endpoint_descriptor *ep_irq_in;
	int i;
	int error = -ENOMEM;

	for (i = 0; xpad_device[i].idVendor; i++) {
		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
		    (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct))
			break;
	}

	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!xpad || !input_dev)
		goto fail1;

	xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
				       GFP_ATOMIC, &xpad->idata_dma);
	if (!xpad->idata)
		goto fail1;

	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
	if (!xpad->irq_in)
		goto fail2;

	xpad->udev = udev;
	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
		xpad->dpad_mapping = dpad_to_buttons;
	xpad->dev = input_dev;
	usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
	strlcat(xpad->phys, "/input0", sizeof(xpad->phys));

	input_dev->name = xpad_device[i].name;
	input_dev->phys = xpad->phys;
	usb_to_input_id(udev, &input_dev->id);
	input_dev->dev.parent = &intf->dev;

	input_set_drvdata(input_dev, xpad);

	input_dev->open = xpad_open;
	input_dev->close = xpad_close;

	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);

	/* set up buttons */
	for (i = 0; xpad_btn[i] >= 0; i++)
		set_bit(xpad_btn[i], input_dev->keybit);
	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
		for (i = 0; xpad_btn_pad[i] >= 0; i++)
			set_bit(xpad_btn_pad[i], input_dev->keybit);

	/* set up axes */
	for (i = 0; xpad_abs[i] >= 0; i++)
		xpad_set_up_abs(input_dev, xpad_abs[i]);
	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES)
		for (i = 0; xpad_abs_pad[i] >= 0; i++)
		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);

	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
	usb_fill_int_urb(xpad->irq_in, udev,
			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
			 xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
			 xpad, ep_irq_in->bInterval);
	xpad->irq_in->transfer_dma = xpad->idata_dma;
	xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	error = input_register_device(xpad->dev);
	if (error)
		goto fail3;

	usb_set_intfdata(intf, xpad);
	return 0;

 fail3:	usb_free_urb(xpad->irq_in);
 fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
 fail1:	input_free_device(input_dev);
	kfree(xpad);
	return error;

}
コード例 #19
0
static int usb_remote_probe(struct usb_interface *intf,
				const struct usb_device_id *id)
{
	struct usb_device *dev = NULL;
	struct usb_host_interface *idesc = NULL;
	struct usb_host_endpoint *ep_ctl2;
#else
static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum,
				const struct usb_device_id *id)
{
	struct usb_interface *intf;
	struct usb_interface_descriptor *idesc;
	struct usb_endpoint_descriptor *ep_ctl2;
#endif
	struct igorplug *ir = NULL;
	struct lirc_driver *driver = NULL;
	int devnum, pipe, maxp;
	int minor = 0;
	char buf[63], name[128] = "";
	int mem_failure = 0;
	int ret;

	dprintk(": usb probe called.\n");

#if defined(KERNEL_2_5)
	dev = interface_to_usbdev(intf);

#  if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5)
	idesc = &intf->altsetting[intf->act_altsetting];  /* in 2.6.4 */
#  else
	idesc = intf->cur_altsetting;  /* in 2.6.6 */
#  endif

	if (idesc->desc.bNumEndpoints != 1)
		return -ENODEV;
	ep_ctl2 = idesc->endpoint;
	if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK)
	    != USB_DIR_IN)
	    || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
	    != USB_ENDPOINT_XFER_CONTROL)
		return -ENODEV;
	pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress);
#else
	intf = &dev->actconfig->interface[ifnum];
	idesc = &intf->altsetting[intf->act_altsetting];
	if (idesc->bNumEndpoints != 1)
		return NULL;
	ep_ctl2 = idesc->endpoint;
	if (((ep_ctl2->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
	    != USB_DIR_IN)
	    || (ep_ctl2->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
	    != USB_ENDPOINT_XFER_CONTROL)
		return NULL;
	pipe = usb_rcvctrlpipe(dev, ep_ctl2->bEndpointAddress);
#endif
	devnum = dev->devnum;
	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

	dprintk(DRIVER_NAME "[%d]: bytes_in_key=%d maxp=%d\n",
		devnum, CODE_LENGTH, maxp);


	mem_failure = 0;
	ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL);
	if (!ir) {
		mem_failure = 1;
		goto mem_failure_switch;
	}

	driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
	if (!driver) {
		mem_failure = 2;
		goto mem_failure_switch;
	}

#if defined(KERNEL_2_5)
	ir->buf_in = usb_buffer_alloc(dev,
			      DEVICE_BUFLEN+DEVICE_HEADERLEN,
			      GFP_ATOMIC, &ir->dma_in);
#else
	ir->buf_in = kmalloc(DEVICE_BUFLEN+DEVICE_HEADERLEN,
			     GFP_KERNEL);
#endif
	if (!ir->buf_in) {
		mem_failure = 3;
		goto mem_failure_switch;
	}

	strcpy(driver->name, DRIVER_NAME " ");
	driver->minor = -1;
	driver->code_length = CODE_LENGTH * 8; /* in bits */
	driver->features = LIRC_CAN_REC_MODE2;
	driver->data = ir;
	driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES;
	driver->set_use_inc = &set_use_inc;
	driver->set_use_dec = &set_use_dec;
	driver->sample_rate = sample_rate;    /* per second */
	driver->add_to_buf = &usb_remote_poll;
#ifdef LIRC_HAVE_SYSFS
	driver->dev = &intf->dev;
#endif
	driver->owner = THIS_MODULE;

	minor = lirc_register_driver(driver);
	if (minor < 0)
		mem_failure = 9;

mem_failure_switch:

	switch (mem_failure) {
	case 9:
#if defined(KERNEL_2_5)
		usb_buffer_free(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN,
			ir->buf_in, ir->dma_in);
#else
		kfree(ir->buf_in);
#endif
	case 3:
		kfree(driver);
	case 2:
		kfree(ir);
	case 1:
		printk(KERN_ERR DRIVER_NAME "[%d]: out of memory (code=%d)\n",
			devnum, mem_failure);
#if defined(KERNEL_2_5)
		return -ENOMEM;
#else
		return NULL;
#endif
	}

	driver->minor = minor;
	ir->d = driver;
	ir->devnum = devnum;
	ir->usbdev = dev;
	ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN;
	ir->in_space = 1; /* First mode2 event is a space. */
	do_gettimeofday(&ir->last_time);

	if (dev->descriptor.iManufacturer
	    && usb_string(dev, dev->descriptor.iManufacturer,
			  buf, sizeof(buf)) > 0)
		strlcpy(name, buf, sizeof(name));
	if (dev->descriptor.iProduct
	    && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
		snprintf(name + strlen(name), sizeof(name) - strlen(name),
			 " %s", buf);
	printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
	       dev->bus->busnum, devnum);

	/* clear device buffer */
	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
		SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
		/*unused*/0, /*unused*/0,
		/*dummy*/ir->buf_in, /*dummy*/ir->len_in,
		/*timeout*/HZ * USB_CTRL_GET_TIMEOUT);
	if (ret < 0)
		printk(KERN_WARNING DRIVER_NAME
		       "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
			devnum, ret);

#if defined(KERNEL_2_5)
	usb_set_intfdata(intf, ir);
	return 0;
#else
	return ir;
#endif
}


#if defined(KERNEL_2_5)
static void usb_remote_disconnect(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct igorplug *ir = usb_get_intfdata(intf);
#else
static void usb_remote_disconnect(struct usb_device *dev, void *ptr)
{
	struct igorplug *ir = ptr;
#endif

	if (!ir || !ir->d)
		return;

	printk(KERN_INFO DRIVER_NAME
	       "[%d]: usb remote disconnected\n", ir->devnum);

	lirc_unregister_driver(ir->d->minor);

	lirc_buffer_free(ir->d->rbuf);
	kfree(ir->d->rbuf);
	kfree(ir->d);


#if defined(KERNEL_2_5)
	usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in);
#else
	kfree(ir->buf_in);
#endif

	kfree(ir);
}

static struct usb_device_id usb_remote_id_table [] = {
	/* Igor Plug USB (Atmel's Manufact. ID) */
	{ USB_DEVICE(0x03eb, 0x0002) },
	/* Fit PC2 Infrared Adapter */
	{ USB_DEVICE(0x03eb, 0x21fe) },

	/* Terminating entry */
	{ }
};

static struct usb_driver usb_remote_driver = {
	LIRC_THIS_MODULE(.owner = THIS_MODULE)
	.name =		DRIVER_NAME,
	.probe =	usb_remote_probe,
	.disconnect =	usb_remote_disconnect,
	.id_table =	usb_remote_id_table
};

static int __init usb_remote_init(void)
{
	int i;

	printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n");
	printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n");
	dprintk(": debug mode enabled\n");

	i = usb_register(&usb_remote_driver);
	if (i < 0) {
		printk(KERN_ERR DRIVER_NAME
		       ": usb register failed, result = %d\n", i);
		return -ENODEV;
	}

	return 0;
}
コード例 #20
0
ファイル: bcm5974.c プロジェクト: Atrix-Dev-Team/kernel-MB860
static int bcm5974_probe(struct usb_interface *iface,
			 const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(iface);
	const struct bcm5974_config *cfg;
	struct bcm5974 *dev;
	struct input_dev *input_dev;
	int error = -ENOMEM;

	/* find the product index */
	cfg = bcm5974_get_config(udev);

	/* allocate memory for our device state and initialize it */
	dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!dev || !input_dev) {
		err("bcm5974: out of memory");
		goto err_free_devs;
	}

	dev->udev = udev;
	dev->intf = iface;
	dev->input = input_dev;
	dev->cfg = *cfg;
	mutex_init(&dev->pm_mutex);

	/* setup urbs */
	dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->bt_urb)
		goto err_free_devs;

	dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->tp_urb)
		goto err_free_bt_urb;

	dev->bt_data = usb_buffer_alloc(dev->udev,
					dev->cfg.bt_datalen, GFP_KERNEL,
					&dev->bt_urb->transfer_dma);
	if (!dev->bt_data)
		goto err_free_urb;

	dev->tp_data = usb_buffer_alloc(dev->udev,
					dev->cfg.tp_datalen, GFP_KERNEL,
					&dev->tp_urb->transfer_dma);
	if (!dev->tp_data)
		goto err_free_bt_buffer;

	usb_fill_int_urb(dev->bt_urb, udev,
			 usb_rcvintpipe(udev, cfg->bt_ep),
			 dev->bt_data, dev->cfg.bt_datalen,
			 bcm5974_irq_button, dev, 1);

	usb_fill_int_urb(dev->tp_urb, udev,
			 usb_rcvintpipe(udev, cfg->tp_ep),
			 dev->tp_data, dev->cfg.tp_datalen,
			 bcm5974_irq_trackpad, dev, 1);

	/* create bcm5974 device */
	usb_make_path(udev, dev->phys, sizeof(dev->phys));
	strlcat(dev->phys, "/input0", sizeof(dev->phys));

	input_dev->name = "bcm5974";
	input_dev->phys = dev->phys;
	usb_to_input_id(dev->udev, &input_dev->id);
	/* report driver capabilities via the version field */
	input_dev->id.version = cfg->caps;
	input_dev->dev.parent = &iface->dev;

	input_set_drvdata(input_dev, dev);

	input_dev->open = bcm5974_open;
	input_dev->close = bcm5974_close;

	setup_events_to_report(input_dev, cfg);

	error = input_register_device(dev->input);
	if (error)
		goto err_free_buffer;

	/* save our data pointer in this interface device */
	usb_set_intfdata(iface, dev);

	return 0;

err_free_buffer:
	usb_buffer_free(dev->udev, dev->cfg.tp_datalen,
		dev->tp_data, dev->tp_urb->transfer_dma);
err_free_bt_buffer:
	usb_buffer_free(dev->udev, dev->cfg.bt_datalen,
		dev->bt_data, dev->bt_urb->transfer_dma);
err_free_urb:
	usb_free_urb(dev->tp_urb);
err_free_bt_urb:
	usb_free_urb(dev->bt_urb);
err_free_devs:
	usb_set_intfdata(iface, NULL);
	input_free_device(input_dev);
	kfree(dev);
	return error;
}
コード例 #21
0
static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface = intf->cur_altsetting;
	struct usb_endpoint_descriptor *endpoint;
	struct wacom *wacom;
	struct wacom_wac *wacom_wac;
	struct wacom_features *features;
	struct input_dev *input_dev;
	int error = -ENOMEM;
	char rep_data[2], limit = 0;
	struct hid_descriptor *hid_desc;

	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
	wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!wacom || !input_dev || !wacom_wac)
		goto fail1;

	wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
	if (!wacom_wac->data)
		goto fail1;

	wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!wacom->irq)
		goto fail2;

	wacom->usbdev = dev;
	wacom->dev = input_dev;
	wacom->intf = intf;
	mutex_init(&wacom->lock);
	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));

	wacom_wac->features = features = get_wacom_feature(id);
	BUG_ON(features->pktlen > 10);

	input_dev->name = wacom_wac->features->name;
	wacom->wacom_wac = wacom_wac;
	usb_to_input_id(dev, &input_dev->id);

	input_dev->dev.parent = &intf->dev;

	input_set_drvdata(input_dev, wacom);

	input_dev->open = wacom_open;
	input_dev->close = wacom_close;

	endpoint = &intf->cur_altsetting->endpoint[0].desc;

	/* Initialize touch_x_max and touch_y_max in case it is not defined */
	if (wacom_wac->features->type == TABLETPC) {
		features->touch_x_max = 1023;
		features->touch_y_max = 1023;
	} else {
		features->touch_x_max = 0;
		features->touch_y_max = 0;
	}

	/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
	if (wacom_wac->features->type == TABLETPC) {
		if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
			if (usb_get_extra_descriptor(&interface->endpoint[0],
						     HID_DEVICET_REPORT, &hid_desc)) {
				printk("wacom: can not retrive extra class descriptor\n");
				goto fail2;
			}
		}
		error = wacom_parse_hid(intf, hid_desc, wacom_wac);
		if (error)
			goto fail2;
	}

	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
		BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
	input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
	if (features->type == TABLETPC) {
		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
		input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
		input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
	}
	input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);

	wacom_init_input_dev(input_dev, wacom_wac);

	usb_fill_int_urb(wacom->irq, dev,
			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
			 wacom_wac->data, wacom_wac->features->pktlen,
			 wacom_sys_irq, wacom, endpoint->bInterval);
	wacom->irq->transfer_dma = wacom->data_dma;
	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	error = input_register_device(wacom->dev);
	if (error)
		goto fail3;

	/*
	 * Ask the tablet to report tablet data if it is not a Tablet PC.
	 * Repeat until it succeeds
	 */
	if (wacom_wac->features->type != TABLETPC) {
		do {
			rep_data[0] = 2;
			rep_data[1] = 2;
			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
						2, rep_data, 2);
			if (error >= 0)
				error = usb_get_report(intf,
						WAC_HID_FEATURE_REPORT, 2,
						rep_data, 2);
		} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
	}

	usb_set_intfdata(intf, wacom);
	return 0;

 fail3:	usb_free_urb(wacom->irq);
 fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
 fail1:	input_free_device(input_dev);
	kfree(wacom);
	kfree(wacom_wac);
	return error;
}
コード例 #22
0
ファイル: usb-skeleton.c プロジェクト: 274914765/C
static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
{
    struct usb_skel *dev;
    int retval = 0;
    struct urb *urb = NULL;
    char *buf = NULL;
    size_t writesize = min(count, (size_t)MAX_TRANSFER);

    dev = (struct usb_skel *)file->private_data;

    /* verify that we actually have some data to write */
    if (count == 0)
        goto exit;

    /* limit the number of URBs in flight to stop a user from using up all RAM */
    if (down_interruptible(&dev->limit_sem)) {
        retval = -ERESTARTSYS;
        goto exit;
    }

    spin_lock_irq(&dev->err_lock);
    if ((retval = dev->errors) < 0) {
        /* any error is reported once */
        dev->errors = 0;
        /* to preserve notifications about reset */
        retval = (retval == -EPIPE) ? retval : -EIO;
    }
    spin_unlock_irq(&dev->err_lock);
    if (retval < 0)
        goto error;

    /* create a urb, and a buffer for it, and copy the data to the urb */
    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb) {
        retval = -ENOMEM;
        goto error;
    }

    buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
    if (!buf) {
        retval = -ENOMEM;
        goto error;
    }

    if (copy_from_user(buf, user_buffer, writesize)) {
        retval = -EFAULT;
        goto error;
    }

    /* this lock makes sure we don't submit URBs to gone devices */
    mutex_lock(&dev->io_mutex);
    if (!dev->interface) {        /* disconnect() was called */
        mutex_unlock(&dev->io_mutex);
        retval = -ENODEV;
        goto error;
    }

    /* initialize the urb properly */
    usb_fill_bulk_urb(urb, dev->udev,
              usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
              buf, writesize, skel_write_bulk_callback, dev);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
    usb_anchor_urb(urb, &dev->submitted);

    /* send the data out the bulk port */
    retval = usb_submit_urb(urb, GFP_KERNEL);
    mutex_unlock(&dev->io_mutex);
    if (retval) {
        err("%s - failed submitting write urb, error %d", __func__, retval);
        goto error_unanchor;
    }

    /* release our reference to this urb, the USB core will eventually free it entirely */
    usb_free_urb(urb);


    return writesize;

error_unanchor:
    usb_unanchor_urb(urb);
error:
    if (urb) {
        usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
        usb_free_urb(urb);
    }
    up(&dev->limit_sem);

exit:
    return retval;
}
コード例 #23
0
ファイル: mod.c プロジェクト: PeteHemery/Embedded-Group-Work
/* 7 bytes max write!
   first byte
      bit 7 - flush buffer (buffer will only contain result of this command)
      bit 6 - query? (1 = query/read, 0 = set/write) if query is set, this is a single byte command
      bit 5 - PORTA dir present   "@00D0%02X\r"
      bit 4 - PORTB dir present   "@00D1%02X\r"
      bit 3 - PORTC dir present   "@00D2%02X\r"
      bit 2 - PORTA data present  "@00P0%02X\r"
      bit 1 - PORTB data present  "@00P1%02X\r"
      bit 0 - PORTC data present  "@00P2%02X\r"
   
*/
static ssize_t diodev_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos) {
#define CMDSEP "\r"
//#define CMDSEP "-"
  struct usb_dio_dev *dev;
  struct usb_dio_urb_chain *bulk_out_urb_chain;
  struct usb_dio_urb_chain *t_urb_chain;
  
  struct urb *urb;
	char *urbBuf;
  
  unsigned char buf[7];
  int ptr;
  
  unsigned char usbBuf[64]; /* max of 48 bytes possible */
  int usbBytes = 0;
  
  int isQuery = 0;
  int retval;
  FUNC_HI();
  
  dev = (struct usb_dio_dev *)file->private_data;
  
  if (count > 7) {
    printk(KERN_ALERT "=== Too many bytes! (%d)\n", (int)count);
    FUNC_ERR();
    return -EIO;
  }
  if (copy_from_user(&(buf[0]),user_buffer,count)) {
    printk(KERN_ALERT "=== Copy error\n");
    FUNC_ERR();
    return -EIO;
  }
  
  if (buf[0] & 0x80) {
    if (down_interruptible(&dev->buffer_sem)) {
      FUNC_ERR();
      return -EINTR;
    }
    dev->buffer_head = 0;
    dev->buffer_tail = 0;
    up(&dev->buffer_sem);
    DPRINTK(KERN_ALERT "=== Flushed\n");
  }
  if (buf[0] & 0x40) {
    isQuery = 1;
    DPRINTK(KERN_ALERT "=== isQuery\n");
  }
  
  /* if is a query... we only need 1 byte! */
  if (buf[0] & 0x40) {
    DPRINTK(KERN_ALERT "=== Looking for %d bytes...\n",1);
    DPRINTK(KERN_ALERT "=== Given %d bytes...\n", (int)count);
    if (count != 1) {
      FUNC_ERR();
      return -EIO;
    }
  } else {
    int c = 1;
    unsigned char t = 0x20;
    while (t) {
      if (buf[0] & t) c++;
      t >>= 1;
      t &= 0x7F;
    }
    DPRINTK(KERN_ALERT "=== Looking for %d bytes...\n",c);
    DPRINTK(KERN_ALERT "=== Given %d bytes...\n", (int)count);
    if (count != c) {
      FUNC_ERR();
      return -EIO;
    }
  }
  
  if (isQuery) {
    DDPRINTK("Q-");
  } else {
    DDPRINTK("W-");
  }
  ptr = 1;
  if (buf[0] & 0x20) {
    DDPRINTK("d0");
    DPRINTK(KERN_ALERT "=== D0\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D0?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D0%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  if (buf[0] & 0x10) {
    DDPRINTK("d1");
    DPRINTK(KERN_ALERT "=== D1\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D1?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D1%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  if (buf[0] & 0x08) {
    DDPRINTK("d2");
    DPRINTK(KERN_ALERT "=== D2\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D2?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00D2%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  if (buf[0] & 0x04) {
    DDPRINTK("p0");
    DPRINTK(KERN_ALERT "=== P0\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P0?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P0%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  if (buf[0] & 0x02) {
    DDPRINTK("p1");
    DPRINTK(KERN_ALERT "=== P1\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P1?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P1%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  if (buf[0] & 0x01) {
    DDPRINTK("p2");
    DPRINTK(KERN_ALERT "=== P2\n");
    if (isQuery) {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P2?"CMDSEP);
    } else {
      usbBytes += snprintf(&(usbBuf[usbBytes]),64-usbBytes,"@00P2%02X"CMDSEP,buf[ptr]);
      ptr++;
    }
  }
  
  DPRINTK(KERN_ALERT "=== STRING:- %s\n",usbBuf);
  
  DPRINTK(KERN_ALERT "=== Building URB...\n");
  
  urb = usb_alloc_urb(0, GFP_KERNEL);
  DPRINTK(KERN_ALERT "** urb @ %p\n",urb);
  if (!urb) {
    FUNC_ERR();
    return -ENOMEM;
  }
  
  DPRINTK(KERN_ALERT "=== Building Buffer (%d)...\n",usbBytes);
  urbBuf = usb_buffer_alloc(dev->dev, usbBytes, GFP_KERNEL, &urb->transfer_dma);
  DPRINTK(KERN_ALERT "** urbBuf @ %p\n",urbBuf);
  if (!urbBuf) {
    usb_free_urb(urb);
    FUNC_ERR();
    return -ENOMEM;
  }
  
  DPRINTK(KERN_ALERT "=== Populating Buffer...\n");
  memcpy(urbBuf, usbBuf, usbBytes);
  
  usb_fill_bulk_urb(urb, dev->dev, dev->bulk_out_endpointPipe, urbBuf, usbBytes, (usb_complete_t)diodev_write_cb, dev);
  urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
  
  t_urb_chain = kmalloc(sizeof(struct usb_dio_urb_chain), GFP_KERNEL);    
  if (dev == NULL) {
    err("Out of Memory");
    FUNC_ERR();
    return -ENOMEM;
  }
  t_urb_chain->next = NULL;
  t_urb_chain->urb = urb;
  if (down_interruptible(&dev->bulk_out_urb_chain_sem)) {
    FUNC_ERR();
    return -EINTR;
  }
  if (dev->bulk_out_urb_chain) {
    DDPRINTK("-C");
    DPRINTK(KERN_ALERT "=== Chaining URB...\n");
    bulk_out_urb_chain = dev->bulk_out_urb_chain;
    while (bulk_out_urb_chain->next) {
      bulk_out_urb_chain = bulk_out_urb_chain->next;
    }
    bulk_out_urb_chain->next = t_urb_chain;
  } else {
    DDPRINTK("-S");
    DPRINTK(KERN_ALERT "=== Submitting URB...\n");
    retval = usb_submit_urb(urb, GFP_KERNEL);
    if (retval) {
      up(&dev->bulk_out_urb_chain_sem);
      DPRINTK(KERN_ALERT "=== URB submit error %d\n", retval);
      usb_buffer_free(dev->dev, usbBytes, urbBuf, urb->transfer_dma);
      usb_free_urb(urb);
      FUNC_ERR();
      return retval;
    }
    dev->bulk_out_urb_chain = t_urb_chain;
  }
  DDPRINTK("\n");
  up(&dev->bulk_out_urb_chain_sem);
  
  DPRINTK(KERN_ALERT "=== diodev_write() Returning!\n");
  FUNC_BYE();
  return count;
}
コード例 #24
0
ファイル: mod.c プロジェクト: PeteHemery/Embedded-Group-Work
void diodev_rx_work(struct work_struct *work) {
  struct usb_dio_workitem *workitem;
  struct usb_dio_dev *dev;
  FUNC_HI();
  workitem = (struct usb_dio_workitem*)work;
  dev = workitem->dev;
  
  DPRINTK(KERN_ALERT "=== diodev_rx_work() hello\n");
  
  if (!workitem->arg) {
    DPRINTK(KERN_ALERT "=== diodev_rx_work() NULL arg!?\n");
  } else {
    struct urb *urb;
    char *buf;
    int i;
    int p;
    char t[128];
    
    DPRINTK(KERN_ALERT "=== diodev_rx_work() non-null arg!\n");
    urb = workitem->arg;
    
    DPRINTK(KERN_ALERT "=== diodev_rx_work() %d\n",urb->actual_length);
    buf = (char *)urb->transfer_buffer;
    
    for (i = 0; i < 127 && i < urb->actual_length; i++) {
      t[i] = buf[i];
      if (t[i] == '\r') t[i] = '-';
    }
    t[i] = '\0';
    DPRINTK(KERN_ALERT "### Recieved [%s] ###\n", t);

    DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail);    
    /* if we have a valid return value */
    DDPRINTK("R");
    if (urb->actual_length == 6 && buf[0] == '!' && buf[1] == '0' && buf[2] == '0' && buf[5] == '\r') {
      char t[3];
      unsigned char c;
      t[0] = buf[3];
      t[1] = buf[4];
      t[2] = '\0';
      sscanf(t,"%02X",(unsigned int *)&c);
      DPRINTK(KERN_ALERT "### Recieved 0x%02X ###\n", c);
      if (down_interruptible(&dev->buffer_sem)) {
        workitem->arg = NULL;
        diodev_rx_setup(dev);
        FUNC_ERR();
        return;
      }
      DPRINTK(KERN_ALERT "=== diodev_rx_work() success down(buffer_sem)...\n");
      if (!((dev->buffer_tail == USB_DIO_DEV_BUFFERSIZE && dev->buffer_head == 0) ||
          (dev->buffer_tail == dev->buffer_head - 1))) {
        
        dev->buffer[dev->buffer_tail] = c;
        dev->buffer_tail++;
        if (dev->buffer_tail >= USB_DIO_DEV_BUFFERSIZE) dev->buffer_tail = 0;
        DPRINTK(KERN_ALERT "### Added to buffer...\n");
        /* if the lock fails... then it is already locked, so unlock it! */
        /* if the lock succeeds... then it is not already locked, but is now... so unlock it! */
        p = down_trylock(&dev->buffer_empty_sem);
        DPRINTK(KERN_ALERT "### Kicking sem...\n");
        up(&dev->buffer_empty_sem);
        DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail);
      } else {
        DPRINTK(KERN_ALERT "### Buffer full...\n");
      }
      DDPRINTK("-0x%02X", c);
      up(&dev->buffer_sem);
    } else {
      DDPRINTK("-X");
    }
    DDPRINTK("\n");
    DPRINTK(KERN_ALERT "%%%%%% %d - %d\n",dev->buffer_head,dev->buffer_tail);
    
    usb_buffer_free(dev->dev, dev->bulk_in_size, urb->transfer_buffer, urb->transfer_dma);
    usb_free_urb(urb);
    
  }
  workitem->arg = NULL;
  
  diodev_rx_setup(dev);
  DPRINTK(KERN_ALERT "=== diodev_rx_work() returning\n");
  FUNC_BYE();
}
コード例 #25
0
ファイル: lighty.c プロジェクト: cboylan/CS572_Demo_Firmware
/*
 * IOCTL
 */
int lighty_ioctl(struct inode * i_node, struct file * file, unsigned int cmd,
                                                            unsigned long arg)
{
	int err = 0;
	int retval = 0;
	struct urb *usb_led;
	char command; // a, b, c ,d, e, f
	char *buf;
	struct usb_lighty *dev = file->private_data;
       /*
        * extract the type and number bitfields, and don't decode
        * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
        */
        if (_IOC_TYPE(cmd) != LIGHTY_IOCTL_MAGIC)
        {
                printk(KERN_NOTICE
                        "lighty_ioctl: !lighty_IOC_MAGIC\n");
                return -ENOTTY;
        }
        if (_IOC_NR(cmd) > LIGHTY_IOCTL_MAX)
        {
                printk(KERN_NOTICE
                        "lighty_ioctl:  > lighty_IOC_MAXNR\n");
                return -ENOTTY;
        }

       /*
        * If not root/sysadmin, go away 
        */
        if (! capable (CAP_SYS_ADMIN))
                return -EPERM;

        /*
         * the direction is a bitmask, and VERIFY_WRITE catches R/W
         * transfers. `Type' is user-oriented, while
         * access_ok is kernel-oriented, so the concept of "read" and
         * "write" is reversed
         */
        if (_IOC_DIR(cmd) & _IOC_READ)
                err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
        else if (_IOC_DIR(cmd) & _IOC_WRITE)
                err =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
        if (err)
        {
                printk(KERN_NOTICE
                        "lighty_ioctl: access !ok\n");
                return -EFAULT;
        }


        switch(cmd) {
                case LIGHTY_IOCTL_1RED:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_1RED\n");
			command = 'a';
			break;
                case LIGHTY_IOCTL_1GREEN:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_1GREEN\n");
			command = 'b';
			break;
                case LIGHTY_IOCTL_1BLUE:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_1BLUE\n");
			command = 'c';
			break;
                case LIGHTY_IOCTL_2RED:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_2RED\n");
			command = 'd';
			break;
                case LIGHTY_IOCTL_2GREEN:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_2GREEN\n");
			command = 'e';
			break;
                case LIGHTY_IOCTL_2BLUE:
                        printk(KERN_NOTICE
                                "LIGHTY_IOCTL_2BLUE\n");
			command = 'f';
			break;
		default:
			printk(KERN_NOTICE
				"Not a known command %x\n", cmd);
			return -ENOMEM;
	}
	usb_led = usb_alloc_urb(0, GFP_KERNEL);
	if (!usb_led) {
		return -ENOMEM;
	}
	buf = usb_buffer_alloc(dev->udev, 64, GFP_KERNEL, &usb_led->transfer_dma);
	if (!buf) {
		printk (KERN_NOTICE "usb_buffer_alloc failed\n");
    		usb_buffer_free(dev->udev, usb_led->transfer_buffer_length,
            		usb_led->transfer_buffer, usb_led->transfer_dma);
		return -ENOMEM;
	}
	buf[0] = command; // a, b, c, d, e or f
	usb_fill_int_urb(usb_led, dev->udev, usb_sndintpipe(dev->udev, dev->intr_out_endpointAddr), buf,
				64, (usb_complete_t)lighty_write_intr_callback, dev, 250);
	usb_led->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
	if( (retval = usb_submit_urb(usb_led, GFP_KERNEL)) ) {
		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
	}
	return 0;
}
コード例 #26
0
ファイル: xpad.c プロジェクト: maraz/linux-2.6
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct usb_xpad *xpad;
	struct input_dev *input_dev;
	struct usb_endpoint_descriptor *ep_irq_in;
	int i;
	int error = -ENOMEM;

	for (i = 0; xpad_device[i].idVendor; i++) {
		if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
		    (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct))
			break;
	}

	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!xpad || !input_dev)
		goto fail1;

	xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
				       GFP_KERNEL, &xpad->idata_dma);
	if (!xpad->idata)
		goto fail1;

	xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL);
	if (!xpad->irq_in)
		goto fail2;

	xpad->udev = udev;
	xpad->dpad_mapping = xpad_device[i].dpad_mapping;
	xpad->xtype = xpad_device[i].xtype;
	if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
		xpad->dpad_mapping = !dpad_to_buttons;
	if (xpad->xtype == XTYPE_UNKNOWN) {
		if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
			if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
				xpad->xtype = XTYPE_XBOX360W;
			else
				xpad->xtype = XTYPE_XBOX360;
		} else
			xpad->xtype = XTYPE_XBOX;
	}
	xpad->dev = input_dev;
	usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
	strlcat(xpad->phys, "/input0", sizeof(xpad->phys));

	input_dev->name = xpad_device[i].name;
	input_dev->phys = xpad->phys;
	usb_to_input_id(udev, &input_dev->id);
	input_dev->dev.parent = &intf->dev;

	input_set_drvdata(input_dev, xpad);

	input_dev->open = xpad_open;
	input_dev->close = xpad_close;

	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);

	/* set up buttons */
	for (i = 0; xpad_common_btn[i] >= 0; i++)
		set_bit(xpad_common_btn[i], input_dev->keybit);
	if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
		for (i = 0; xpad360_btn[i] >= 0; i++)
			set_bit(xpad360_btn[i], input_dev->keybit);
	else
		for (i = 0; xpad_btn[i] >= 0; i++)
			set_bit(xpad_btn[i], input_dev->keybit);
	if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
		for (i = 0; xpad_btn_pad[i] >= 0; i++)
			set_bit(xpad_btn_pad[i], input_dev->keybit);

	/* set up axes */
	for (i = 0; xpad_abs[i] >= 0; i++)
		xpad_set_up_abs(input_dev, xpad_abs[i]);
	if (xpad->dpad_mapping == MAP_DPAD_TO_AXES)
		for (i = 0; xpad_abs_pad[i] >= 0; i++)
		    xpad_set_up_abs(input_dev, xpad_abs_pad[i]);

	error = xpad_init_output(intf, xpad);
	if (error)
		goto fail2;

	error = xpad_init_ff(xpad);
	if (error)
		goto fail3;

	error = xpad_led_probe(xpad);
	if (error)
		goto fail3;

	ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
	usb_fill_int_urb(xpad->irq_in, udev,
			 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
			 xpad->idata, XPAD_PKT_LEN, xpad_irq_in,
			 xpad, ep_irq_in->bInterval);
	xpad->irq_in->transfer_dma = xpad->idata_dma;
	xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	error = input_register_device(xpad->dev);
	if (error)
		goto fail4;

	usb_set_intfdata(intf, xpad);

	/*
	 * Submit the int URB immediatly rather than waiting for open
	 * because we get status messages from the device whether
	 * or not any controllers are attached.  In fact, it's
	 * exactly the message that a controller has arrived that
	 * we're waiting for.
	 */
	if (xpad->xtype == XTYPE_XBOX360W) {
		xpad->irq_in->dev = xpad->udev;
		error = usb_submit_urb(xpad->irq_in, GFP_KERNEL);
		if (error)
			goto fail4;

		/*
		 * Setup the message to set the LEDs on the
		 * controller when it shows up
		 */
		xpad->bulk_out = usb_alloc_urb(0, GFP_KERNEL);
		if(!xpad->bulk_out)
			goto fail5;

		xpad->bdata = kzalloc(XPAD_PKT_LEN, GFP_KERNEL);
		if(!xpad->bdata)
			goto fail6;

		xpad->bdata[2] = 0x08;
		switch (intf->cur_altsetting->desc.bInterfaceNumber) {
		case 0:
			xpad->bdata[3] = 0x42;
			break;
		case 2:
			xpad->bdata[3] = 0x43;
			break;
		case 4:
			xpad->bdata[3] = 0x44;
			break;
		case 6:
			xpad->bdata[3] = 0x45;
		}

		ep_irq_in = &intf->cur_altsetting->endpoint[1].desc;
		usb_fill_bulk_urb(xpad->bulk_out, udev,
				usb_sndbulkpipe(udev, ep_irq_in->bEndpointAddress),
				xpad->bdata, XPAD_PKT_LEN, xpad_bulk_out, xpad);
	}

	return 0;

 fail6:	usb_free_urb(xpad->bulk_out);
 fail5:	usb_kill_urb(xpad->irq_in);
 fail4:	usb_free_urb(xpad->irq_in);
 fail3:	xpad_deinit_output(xpad);
 fail2:	usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma);
 fail1:	input_free_device(input_dev);
	kfree(xpad);
	return error;

}
コード例 #27
-1
ファイル: usblp.c プロジェクト: rcplay/snake-os
static int usblp_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev (intf);
    struct usblp *usblp = NULL;
    int protocol;
    int retval;

    /* Malloc and start initializing usblp structure so we can use it
     * directly. */
    if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
        err("out of memory for usblp");
        goto abort;
    }
    usblp->dev = dev;
    init_MUTEX (&usblp->sem);
    init_waitqueue_head(&usblp->wait);
    usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
    usblp->intf = intf;

    usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
    if (!usblp->writeurb) {
        err("out of memory");
        goto abort;
    }
    usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
    if (!usblp->readurb) {
        err("out of memory");
        goto abort;
    }

    /* Malloc device ID string buffer to the largest expected length,
     * since we can re-query it on an ioctl and a dynamic string
     * could change in length. */
    if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
        err("out of memory for device_id_string");
        goto abort;
    }

    usblp->writebuf = usblp->readbuf = NULL;
    usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
    usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
    /* Malloc write & read buffers.  We somewhat wastefully
     * malloc both regardless of bidirectionality, because the
     * alternate setting can be changed later via an ioctl. */
    if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
                            GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
        err("out of memory for write buf");
        goto abort;
    }
    if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
                                            GFP_KERNEL, &usblp->readurb->transfer_dma))) {
        err("out of memory for read buf");
        goto abort;
    }

    /* Allocate buffer for printer status */
    usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
    if (!usblp->statusbuf) {
        err("out of memory for statusbuf");
        goto abort;
    }

    /* Lookup quirks for this printer. */
    usblp->quirks = usblp_quirks(
                        le16_to_cpu(dev->descriptor.idVendor),
                        le16_to_cpu(dev->descriptor.idProduct));

    /* Analyze and pick initial alternate settings and endpoints. */
    protocol = usblp_select_alts(usblp);
    if (protocol < 0) {
        dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
            le16_to_cpu(dev->descriptor.idVendor),
            le16_to_cpu(dev->descriptor.idProduct));
        goto abort;
    }

    /* Setup the selected alternate setting and endpoints. */
    if (usblp_set_protocol(usblp, protocol) < 0)
        goto abort;

    /* Retrieve and store the device ID string. */
    usblp_cache_device_id_string(usblp);
    device_create_file(&intf->dev, &dev_attr_ieee1284_id);

#ifdef DEBUG
    usblp_check_status(usblp, 0);
#endif

    usb_set_intfdata (intf, usblp);

    usblp->present = 1;

    retval = usb_register_dev(intf, &usblp_class);
    if (retval) {
        err("Not able to get a minor for this device.");
        goto abort_intfdata;
    }
    usblp->minor = intf->minor;
    info("usblp%d: USB %sdirectional printer dev %d "
         "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
         usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
         usblp->ifnum,
         usblp->protocol[usblp->current_protocol].alt_setting,
         usblp->current_protocol,
         le16_to_cpu(usblp->dev->descriptor.idVendor),
         le16_to_cpu(usblp->dev->descriptor.idProduct));

    return 0;

abort_intfdata:
    usb_set_intfdata (intf, NULL);
    device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
abort:
    if (usblp) {
        if (usblp->writebuf)
            usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
                             usblp->writebuf, usblp->writeurb->transfer_dma);
        if (usblp->readbuf)
            usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
                             usblp->readbuf, usblp->writeurb->transfer_dma);
        kfree(usblp->statusbuf);
        kfree(usblp->device_id_string);
        usb_free_urb(usblp->writeurb);
        usb_free_urb(usblp->readurb);
        kfree(usblp);
    }
    return -EIO;
}