/* * 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); } }
/***************************************************************************** * _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); } }
/* 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; }
/*-------------------------------------------------------------------*/ 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); }
/* * 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); }
/*-------------------------------------------------------------------*/ 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; }
/* * 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); }
/*-------------------------------------------------------------------*/ 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; }
// ########################################################################################################## // # 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; }
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; }