Пример #1
0
/*
 * Processes the data read from the device.
 */
static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
{
	snd_usb_midi_in_endpoint_t* ep = urb->context;

	if (urb->status == 0) {
		dump_urb("received", urb->transfer_buffer, urb->actual_length);
		ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
						   urb->actual_length);
	} else {
		int err = snd_usbmidi_urb_error(urb->status);
		if (err < 0) {
			if (err != -ENODEV) {
				ep->error_resubmit = 1;
				mod_timer(&ep->umidi->error_timer,
					  jiffies + ERROR_DELAY_JIFFIES);
			}
			return;
		}
	}

	if (usb_pipe_needs_resubmit(urb->pipe)) {
		urb->dev = ep->umidi->chip->dev;
		snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
	}
}
Пример #2
0
/*****************************************************************************
 *      _usb_urb_complete                                                    *
 ****************************************************************************/
static void _usb_urb_complete(struct usb_driver *ud, long urb_id)
{
	/* find the corresponding URB in the urb_pending list. */
	struct usb_urb * urb = NULL;
	if (pending_urbs != NULL) {
		if (pending_urbs->urb_id == urb_id) {
			urb = pending_urbs;
			pending_urbs = urb->next;
		} else {
			struct usb_urb *u = pending_urbs;
			while (u->next) {
				if (u->next->urb_id == urb_id) {
					urb       = u->next;
					u->next   = u->next->next;
					urb->next = NULL;
					break;
				}
				u = u->next;
			}
		}
	}

	/* Did we find a URB? */
	if (urb != NULL) {
		/* revoke grant */
		cpf_revoke(urb->gid);
		/* call completion handler */
#if 0
		dump_urb(urb);
#endif
		ud->urb_completion(urb);
	} else {
		printf("WARN: _usb_urb_complete: did not find URB with ID %ld", urb_id);
	}
}
Пример #3
0
/* helper function to send static data that may not DMA-able */
static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
				 const void *data, int len)
{
	int err;
	void *buf = kmalloc(len, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;
	memcpy(buf, data, len);
	dump_urb("sending", buf, len);
	err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
			   NULL, 250);
	kfree(buf);
	return err;
}
Пример #4
0
/*-------------------------------------------------------------------*/
static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
{
	unsigned long flags;
	pbuff_t b;

	dbg("dabusb_cancel_queue");

	spin_lock_irqsave (&s->lock, flags);

	list_for_each_entry(b, q, buff_list) {
#ifdef DEBUG
		dump_urb(b->purb);
#endif
		usb_unlink_urb (b->purb);
	}
Пример #5
0
/*
 * This is called when some data should be transferred to the device
 * (from one or more substreams).
 */
void snd_hdjmidi_do_output(struct snd_hdjmidi_out_endpoint* ep)
{
	struct urb* urb = ep->urb;
	unsigned long flags;
	
#ifdef RENDER_DATA_PRINTK
	snd_printk(KERN_INFO"%s()\n",__FUNCTION__);
#endif
	spin_lock_irqsave(&ep->buffer_lock, flags);
	if (ep->urb_active || atomic_read(&ep->umidi->chip->shutdown)==1) {
		spin_unlock_irqrestore(&ep->buffer_lock, flags);
		return;
	}
	
#ifdef THROTTLE_MP3_RENDER
	/* Only the mp3 need to throttled because it is HID, and we don't want to send
	 *  faster than every 8 ms */
	if (ep->umidi->chip->product_code==DJCONTROLLER_PRODUCT_CODE) {
			if (time_before(jiffies, ep->last_send_time)) {
				mod_timer(&ep->render_delay_timer,
							(long)ep->last_send_time-
							(long)jiffies);
				spin_unlock_irqrestore(&ep->buffer_lock, flags);
				return;
			}
	}
#endif

	urb->transfer_buffer_length = 0;
	ep->umidi->usb_protocol_ops->output(ep);

	if (urb->transfer_buffer_length > 0) {
		dump_urb("sending", urb->transfer_buffer,
			 urb->transfer_buffer_length);
		urb->dev = ep->umidi->chip->dev;
		ep->urb_active = snd_hdjmidi_submit_urb(ep->umidi, urb, GFP_ATOMIC) >= 0;

		/* new send time allowed */
		ep->umidi->endpoints[0].out->last_send_time = jiffies + 
			(THROTTLE_MP3_RENDER_RATE*HZ)/1000;
	}
	spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
Пример #6
0
/*-------------------------------------------------------------------*/
static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
{
	unsigned long flags;
	struct list_head *p;
	pbuff_t b;

	dbg("dabusb_cancel_queue");

	spin_lock_irqsave (&s->lock, flags);

	for (p = q->next; p != q; p = p->next) {
		b = list_entry (p, buff_t, buff_list);

#ifdef DEBUG
		dump_urb(b->purb);
#endif
		usb_unlink_urb (b->purb);
	}
	spin_unlock_irqrestore (&s->lock, flags);
	return 0;
}
Пример #7
0
/*
 * This is called when some data should be transferred to the device
 * (from one or more substreams).
 */
static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
{
	struct urb* urb = ep->urb;
	unsigned long flags;

	spin_lock_irqsave(&ep->buffer_lock, flags);
	if (ep->urb_active || ep->umidi->chip->shutdown) {
		spin_unlock_irqrestore(&ep->buffer_lock, flags);
		return;
	}

	urb->transfer_buffer_length = 0;
	ep->umidi->usb_protocol_ops->output(ep);

	if (urb->transfer_buffer_length > 0) {
		dump_urb("sending", urb->transfer_buffer,
			 urb->transfer_buffer_length);
		urb->dev = ep->umidi->chip->dev;
		ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0;
	}
	spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
Пример #8
0
/*-------------------------------------------------------------------*/
static int dabusb_free_queue (struct list_head *q)
{
	struct list_head *tmp;
	struct list_head *p;
	pbuff_t b;

	dbg("dabusb_free_queue");
	for (p = q->next; p != q;) {
		b = list_entry (p, buff_t, buff_list);

#ifdef DEBUG 
		dump_urb(b->purb);
#endif
		if (b->purb->transfer_buffer)
			kfree (b->purb->transfer_buffer);
		usb_free_urb(b->purb);
		tmp = p->next;
		list_del (p);
		kfree (b);
		p = tmp;
	}

	return 0;
}
Пример #9
0
// ##########################################################################################################
// #  Interpose IOCTL
// ##########################################################################################################
int ioctl(int d, int request, void *pnt)
{
    int ret;
    static int (*real_ioctl)(int d, int request, void *pnt) = NULL;
    int flag_exec_ioctl = 1;

    if (!real_ioctl)
        real_ioctl= dlsym(RTLD_NEXT, "ioctl");


    /*
        USBDEVFS_CLAIMINTERFACE

        This is used to force usbfs to claim a specific interface, which has not previously
        been claimed by usbfs or any other kernel driver. The ioctl parameter is an integer
        holding the number of the interface (bInterfaceNumber from descriptor).

        Note that if your driver doesn't claim an interface before trying to use one of its
        endpoints, and no other driver has bound to it, then the interface is automatically
        claimed by usbfs.

        This claim will be released by a RELEASEINTERFACE ioctl, or by closing the file
        descriptor. File modification time is not updated by this request.
    */
    if (USBDEVFS_CLAIMINTERFACE==request){
#if NO_POINTERS==0
        printf("  USBDEVFS_CLAIMINTERFACE  %d\n",*(int*)pnt);
#else
        printf("  USBDEVFS_CLAIMINTERFACE\n");
#endif
    }

    /*
        USBDEVFS_RELEASEINTERFACE
        This is used to release the claim usbfs made on interface, either implicitly or because
        of a USBDEVFS_CLAIMINTERFACE call, before the file descriptor is closed. The ioctl
        parameter is an integer holding the number of the interface (bInterfaceNumber from
        descriptor); File modification time is not updated by this request.

        Warning
        No security check is made to ensure that the task which made the claim is the one which
        is releasing it. This means that user mode driver may interfere other ones.
    */
    if (USBDEVFS_RELEASEINTERFACE==request){
#if NO_POINTERS==0
        printf("  USBDEVFS_RELEASEINTERFACE %d\n",*(int*)pnt);
#else
        printf("  USBDEVFS_RELEASEINTERFACE\n");
#endif
    }

    /*
        USBDEVFS_RESETEP
        Resets the data toggle value for an endpoint (bulk or interrupt) to DATA0. The ioctl
        parameter is an integer endpoint number (1 to 15, as identified in the endpoint
        descriptor), with USB_DIR_IN added if the device's endpoint sends data to the host.

        Warning
        Avoid using this request. It should probably be removed. Using it typically means the
        device and driver will lose toggle synchronization. If you really lost synchronization,
        you likely need to completely handshake with the device, using a request like CLEAR_HALT
        or SET_INTERFACE.
    */
    if (USBDEVFS_RESETEP==request){
        unsigned char endPoint = *(unsigned char *)pnt;
        if ( USB_DIR_IN == (USB_DIR_IN & endPoint) )
            printf("  USBDEVFS_RESETEP  %d|USB_DIR_IN\n",endPoint^USB_DIR_IN);
        else
            printf("  USBDEVFS_RESETEP  %d|USB_DIR_OUT\n",endPoint);
    }

    /*
        USBDEVFS_SUBMITURB
    */
    if( USBDEVFS_SUBMITURB==request ){
        struct usbdevfs_urb *urb = (struct usbdevfs_urb *)pnt;
        printf("    USBDEVFS_SUBMITURB\n");
        int direction = urb->endpoint&USB_ENDPOINT_DIR_MASK;
        if (direction==USB_DIR_IN){
            flag_exec_ioctl=0;
            ret = real_ioctl(d,request,pnt);
        }
        urb = (struct usbdevfs_urb*)pnt;
        if (direction==USB_DIR_IN)
            dump_urb(*urb,0);       // do not show contents of the buffer when requesting input
                                    // this will come afterwards in another URB (USBDEVFS_REAPURBNDELAY)
        else
            dump_urb(*urb,1);       // direction OUT: show the packet sent...
        printf("\n");
    }


    /*
        USBDEVFS_RESET
        Does a USB level device reset. The ioctl parameter is ignored. After the reset, this
        rebinds all device interfaces. File modification time is not updated by this request.

        Warning
        Avoid using this call until some usbcore bugs get fixed, since it does not fully
        synchronize device, interface, and driver (not just usbfs) state.
    */
    if (USBDEVFS_RESET==request){
#if NO_POINTERS==0
        printf("  USBDEVFS_RESET %d\n",(int)pnt);
#else
        printf("  USBDEVFS_RESET\n");
#endif
    }

    /*
        USBDEVFS_SETINTERFACE
        Sets the alternate setting for an interface.
        The ioctl parameter is a pointer to a structure like this:

        struct usbdevfs_setinterface {
            unsigned int  interface;
            unsigned int  altsetting;
        }; 

        File modification time is not updated by this request.

        Those struct members are from some interface descriptor applying to the current
        configuration. The interface number is the bInterfaceNumber value, and the
        altsetting number is the bAlternateSetting value. (This resets each endpoint
        in the interface.)
    */
    if (USBDEVFS_SETINTERFACE==request) {
        struct usbdevfs_setinterface setInterface = *(struct usbdevfs_setinterface*)pnt;
        printf("  USBDEVFS_SETINTERFACE\n");
        printf("    bInterfaceNumber  = %d\n",setInterface.interface);
        printf("    bAlternateSetting = %d\n",setInterface.altsetting);
    }

    /*
        USBDEVFS_CLEAR_HALT

        Clears endpoint halt (stall) and resets the endpoint toggle. This is only
        meaningful for bulk or interrupt endpoints. The ioctl parameter is an integer
        endpoint number (1 to 15, as identified in an endpoint descriptor), masked with
        USB_DIR_IN when referring to an endpoint which sends data to the host from the
        device.

        Use this on bulk or interrupt endpoints which have stalled, returning -EPIPE
        status to a data transfer request. Do not issue the control request directly,
        since that could invalidate the host's record of the data toggle.
    */
    if (USBDEVFS_CLEAR_HALT==request) {
        unsigned char endPoint = *(unsigned char *)pnt;
        if ( USB_DIR_IN == (USB_DIR_IN & endPoint) )
            printf("  USBDEVFS_CLEAR_HALT %d|USB_DIR_IN\n",endPoint^USB_DIR_IN);
        else
            printf("  USBDEVFS_CLEAR_HALT %d|USB_DIR_OUT\n",endPoint);
    }


    /*
        NOT SURE ABOUT THIS FUNCTION!!!
    */
    if (USBDEVFS_REAPURBNDELAY==request){
        struct usbdevfs_urb *urb;
#if NO_POINTERS==0
        printf("  USBDEVFS_REAPURBNDELAY   %p\n",pnt);
#else
        printf("  USBDEVFS_REAPURBNDELAY\n");
#endif

        flag_exec_ioctl=0;

        ret = real_ioctl(d,request,pnt);


        // pnt is a pointer to a pointer!
        if ( (!ret) && (struct usbdevfs_urb**)pnt ){
            urb = *(struct usbdevfs_urb**)pnt;
            int direction = urb->endpoint&USB_ENDPOINT_DIR_MASK;

//            if (urb->buffer_length==1024){
//                unsigned char *cp = urb->buffer;
//                for (int jj=0; jj<(1024-20); jj++ )
//                    cp[20+jj] = (unsigned int) jj & 0xff;
//            }

            if (direction==USB_DIR_IN)
                dump_urb(*urb,1);        // this is the answer to an input request, therefore
                                         // we want to dump the packet
            else
                dump_urb(*urb,0);        // this is a REAPURBNDELAY with output direction
                                         // therefore we do not show the packet
        } else
            printf("ret = %d\n",ret);
        printf("\n");
    }



    /*
        NOT SURE ABOUT THIS FUNCTION!!!
    */
    if (USBDEVFS_DISCARDURB==request){
        struct usbdevfs_urb *urb;

        flag_exec_ioctl=0;
        ret = real_ioctl(d,request,pnt);

        // pnt is a pointer to an URB
        if ( (!ret) && (struct usbdevfs_urb*)pnt ){
            urb = (struct usbdevfs_urb*)pnt;
            dump_urb(*urb,1);
        } else
            printf("ret = %d\n",ret);
        printf("\n");
    }



    printf( "\n");
    if (1==flag_exec_ioctl)
        ret = real_ioctl(d,request,pnt);
#if NO_POINTERS==0
    printf("END OF CAPTURE:    %d=IOCTL(%d,0x%x,0x%x)\n",ret,d,request,pnt);
#else
    printf("END OF CAPTURE:    %d=IOCTL(%d,0x--------,0x--------)\n",ret,d);
#endif
    printf("--------------------------------------------------------------\n");

    fflush(stdout);
    return ret;
}
Пример #10
0
u8 mp3w_check_led_state(struct snd_hdjmidi_out_endpoint* ep, u8 called_from_kthread)
{
	int refire = 0, value_to_send;
	u8 toggle_master_r = 0, toggle_master_l = 0, toggle_monitor_l = 0;
	u8 loop_cure_applied = 0;
	u8 monitor_cure_applied = 0;
	unsigned long flags;
	unsigned int bytepos=0;
	unsigned int bitpos=0;
	unsigned int control_num=0;
	unsigned int control_id=0;
	unsigned int toggle_control=0;
	unsigned int max_index = DJ_MP3_HID_OUTPUT_REPORT_LEN-1;

	loop_cure_applied = is_loop_cure_applied(ep->controller_state);
	monitor_cure_applied = is_monitor_cure_applied(ep->controller_state);

	if (loop_cure_applied==0) {
		if (atomic_read(&ep->controller_state->control_details[MP3_OUT_MASTER_TEMPO_R].value)==1 &&
		   (atomic_read(&ep->controller_state->control_details[MP3_OUT_LOOP_R].value)==1 ||
		    atomic_read(&ep->controller_state->control_details[MP3_OUT_LOOP_L].value)==1) ) {
			toggle_master_r = 1;
			refire = 1;
		}
	
		if (atomic_read(&ep->controller_state->control_details[MP3_OUT_MASTER_TEMPO_L].value)==1 &&
		   atomic_read(&ep->controller_state->control_details[MP3_OUT_LOOP_R].value)==1) {
			toggle_master_l = 1;
			refire = 1;
		}
	}
	
	if (monitor_cure_applied==0) {
		if (atomic_read(&ep->controller_state->control_details[MP3_OUT_MASTER_TEMPO_R].value)==1 &&
		   atomic_read(&ep->controller_state->control_details[MP3_OUT_MONITOR_L].value)==1 &&
		   atomic_read(&ep->controller_state->control_details[MP3_OUT_PLAY_PAUSE_L].value)==1) {
			toggle_monitor_l = 1;
			refire = 1;
		}
	}

	/* return either if we determine no action is necessary, or if we are called from interrupt/tasklet
		context, and will signal the work queue to engage and do the work later */
	if ( refire==0 || called_from_kthread==0) {
		return refire;
	}
		
	/* from here on we have been called from the kthread and are thus in process context */
	spin_lock_irqsave(&ep->controller_state->hid_buffer_lock, flags);
	memcpy(ep->controller_state->urb_kt->transfer_buffer,
		ep->controller_state->current_hid_report_data,
		sizeof(ep->controller_state->current_hid_report_data));
	/*controller_state->current_hid_report_data_wq[1] = (~(controller_state->current_hid_report_data_wq[1]&0x1)&1);*/
	spin_unlock_irqrestore(&ep->controller_state->hid_buffer_lock, flags);

	/* clear to proceed */
	for(value_to_send = 0 ; value_to_send < 2 ; value_to_send++) {
		for(control_num = 0; control_num < 3 ; control_num++) {
			if (control_num==0) {
				control_id = MP3_OUT_MASTER_TEMPO_R;
				if (toggle_master_r==1) {
					toggle_control = 1;
				} else {
					toggle_control = 0;
				}
			} else if (control_num==1) {
				control_id = MP3_OUT_MASTER_TEMPO_L;
				if (toggle_master_l==1) {
					toggle_control = 1;
				} else {
					toggle_control = 0;
				}
			} else {
				control_id = MP3_OUT_MONITOR_L;
				if (toggle_monitor_l==1) {
					toggle_control = 1;
				} else {
					toggle_control = 0;
				}
			}
			if (toggle_control==1) {
				bytepos = ep->controller_state->control_details[control_id].byte_number;
				if (bytepos>max_index) {
					snd_printk(KERN_INFO"%s(): bad bytepos:%s, %d\n",
						__FUNCTION__,
						ep->controller_state->control_details[control_id].name,
						bytepos);
					continue;
				}
				bitpos = ep->controller_state->control_details[control_id].bit_number;	
				if (value_to_send==1) {
					((char*)ep->controller_state->urb_kt->transfer_buffer)[bytepos] |= 1<<bitpos;
				} else {
					((char*)ep->controller_state->urb_kt->transfer_buffer)[bytepos] &= ~(1<<bitpos);
				}	
			}
		}

		/* set urb dev and length and fire- synchronously */
		ep->controller_state->urb_kt->dev = ep->umidi->chip->dev;
		ep->controller_state->urb_kt->transfer_buffer_length = DJ_MP3_HID_OUTPUT_REPORT_LEN;
		dump_urb("hid_kt",ep->controller_state->urb_kt->transfer_buffer,ep->controller_state->urb_kt->transfer_buffer_length);
		
		if (snd_hdjmidi_submit_urb(ep->umidi, ep->controller_state->urb_kt, GFP_KERNEL)==0) {
			wait_for_completion(&ep->controller_state->ctl_req_completion_kt);
		}

		/* sleep a bit */
		if (value_to_send==0) {
			/* sleep for the timer period */
			msleep(POLL_PERIOD_MS);
		}
	}

	return refire;
}