/* * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ #include #include "bas_printf.h" #include "usb.h" #include "exceptions.h" #undef USB_MOUSE_DEBUG #ifdef USB_MOUSE_DEBUG #define mse_printf(fmt,args...) bas_printf(fmt ,##args) #else #define mse_printf(fmt,args...) #endif extern void ltoa(char *buf, long n, unsigned long base); extern void call_mousevec(unsigned char *data, void (**mousevec)(void *)); //extern void call_ikbdvec(unsigned char code, _IOREC *iorec, void (**ikbdvec)()); static unsigned char *new; static unsigned char old[8]; static int mouse_installed; /* forward declaration */ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum); /* deregistering the mouse */ int usb_mouse_deregister(struct usb_device *dev) { dev->irq_handle = NULL; if(new != NULL) { usb_free(new); new = NULL; } mouse_installed = 0; mse_printf("USB MOUSE deregister\r\n"); return 1; } /* registering the mouse */ int usb_mouse_register(struct usb_device *dev) { if(!mouse_installed && (dev->devnum != -1) && (usb_mouse_probe(dev, 0) == 1)) { /* Ok, we found a mouse */ mse_printf("USB MOUSE found (USB: %d, devnum: %d)\r\n", dev->usbnum, dev->devnum); mouse_installed = 1; dev->deregister = usb_mouse_deregister; return 1; } /* no USB Mouse found */ return -1; } /* search for mouse and register it if found */ int drv_usb_mouse_init(void) { int i, j; if(mouse_installed) return -1; /* scan all USB Devices */ for(j = 0; j < USB_MAX_BUS; j++) { for(i = 0; i < USB_MAX_DEVICE; i++) { struct usb_device *dev = usb_get_dev_index(i, j); /* get device */ if(dev == NULL) break; if(usb_mouse_register(dev) > 0) return 1; } } /* no USB Mouse found */ return -1; } /************************************************************************** * Low Level drivers */ static void usb_kbd_send_code(unsigned char code) { mse_printf("FIXME: usb_kbd_send_code 0x%x not implemented\r\n", code); } /* Interrupt service routine */ static int usb_mouse_irq(struct usb_device *dev) { #ifdef CONFIG_USB_INTERRUPT_POLLING int level; #endif int i, change = 0; if((dev->irq_status != 0) || (dev->irq_act_len < 3) || (dev->irq_act_len > 8)) { mse_printf("USB MOUSE error %lX, len %d\r\n", dev->irq_status, dev->irq_act_len); return 1; } for(i = 0; i < dev->irq_act_len; i++) { if(new[i] != old[i]) { change = 1; break; } } if(change) { char wheel = 0, buttons, old_buttons; mse_printf("USB MOUSE len:%d %02X %02X %02X %02X %02X %02X\r\n", dev->irq_act_len, new[0], new[1], new[2], new[3], new[4], new[5]); #ifdef CONFIG_USB_INTERRUPT_POLLING level = set_ipl(7); /* mask interrupts */ #endif if((dev->irq_act_len >= 6) && (new[0] == 1)) /* report-ID */ { buttons = new[1]; old_buttons = old[1]; new[0] = ((new[1] & 1) << 1) + ((new[1] & 2) >> 1) + 0xF8; new[1] = new[2]; new[2] = new[3]; wheel = new[4]; } else /* boot report */ { buttons = new[0]; old_buttons = old[0]; new[0] = ((new[0] & 1) << 1) + ((new[0] & 2) >> 1) + 0xF8; if(dev->irq_act_len >= 3) wheel = new[3]; } if((buttons ^ old_buttons) & 4) /* 3rd button */ { if(buttons & 4) { usb_kbd_send_code(0x72); /* ENTER */ usb_kbd_send_code(0xF2); } } if(wheel != 0) /* actually like Eiffel */ { #define REPEAT_WHEEL 3 int i; if(wheel > 0) { for(i = 0; i < REPEAT_WHEEL; i++) { usb_kbd_send_code(0x48); /* UP */ usb_kbd_send_code(0xC8); } } else { for(i = 0; i < REPEAT_WHEEL; i++) { usb_kbd_send_code(0x50); /* DOWN */ usb_kbd_send_code(0xD0); } } } xprintf("FIXME: call_mousevec(new, mousevec) not implemented\r\n"); //if(mousevec != NULL) //call_mousevec(new, mousevec); #ifdef CONFIG_USB_INTERRUPT_POLLING set_ipl(level); #endif old[0] = new[0]; old[1] = new[1]; old[2] = new[2]; old[3] = new[3]; old[4] = new[4]; old[5] = new[5]; } return 1; /* install IRQ Handler again */ } /* probes the USB device dev for mouse type */ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum) { struct usb_interface_descriptor *iface; struct usb_endpoint_descriptor *ep; int pipe, maxp; if(dev->descriptor.bNumConfigurations != 1) return 0; iface = &dev->config.if_desc[ifnum]; if(iface->bInterfaceClass != 3) return 0; if(iface->bInterfaceSubClass != 1) return 0; if(iface->bInterfaceProtocol != 2) return 0; if(iface->bNumEndpoints != 1) return 0; ep = &iface->ep_desc[0]; if(!(ep->bEndpointAddress & 0x80)) return 0; if((ep->bmAttributes & 3) != 3) return 0; new = (unsigned char *)usb_malloc(8); if(new == NULL) return 0; mse_printf("USB MOUSE found set protocol...\r\n"); /* ok, we found a USB Mouse, install it */ pipe = usb_rcvintpipe(dev, ep->bEndpointAddress); maxp = usb_maxpacket(dev, pipe); // if(maxp < 6) // usb_set_protocol(dev, iface->bInterfaceNumber, 0); /* boot */ // else usb_set_protocol(dev, iface->bInterfaceNumber, 1); /* report */ mse_printf("USB MOUSE found set idle...\r\n"); usb_set_idle(dev, iface->bInterfaceNumber, 0, 0); /* report infinite */ memset(&new[0], 0, 8); memset(&old[0], 0, 8); dev->irq_handle = usb_mouse_irq; mse_printf("USB MOUSE enable interrupt pipe (maxp: %d)...\r\n", maxp); usb_submit_int_msg(dev, pipe, &new[0], maxp > 8 ? 8 : maxp, ep->bInterval); return 1; }