1 /* $NetBSD: uipad.c,v 1.9 2020/01/07 06:42:26 maxv Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: uipad.c,v 1.9 2020/01/07 06:42:26 maxv Exp $"); 34 35 #ifdef _KERNEL_OPT 36 #include "opt_usb.h" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/device.h> 43 #include <sys/ioctl.h> 44 #include <sys/conf.h> 45 #include <sys/file.h> 46 #include <sys/select.h> 47 #include <sys/proc.h> 48 #include <sys/vnode.h> 49 #include <sys/poll.h> 50 #include <sys/bus.h> 51 52 #include <dev/usb/usb.h> 53 #include <dev/usb/usbdi.h> 54 #include <dev/usb/usbdi_util.h> 55 #include <dev/usb/usbdivar.h> 56 57 #include <dev/usb/usbdevs.h> 58 59 #ifdef UIPAD_DEBUG 60 #define DPRINTF(x) if (uipaddebug) printf x 61 #define DPRINTFN(n, x) if (uipaddebug > n) printf x 62 int uipaddebug = 0; 63 #else 64 #define DPRINTF(x) 65 #define DPRINTFN(n, x) 66 #endif 67 68 struct uipad_softc { 69 device_t sc_dev; 70 struct usbd_device * sc_udev; 71 }; 72 73 static const struct usb_devno uipad_devs[] = { 74 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD }, 75 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD_2 }, 76 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD_3 }, 77 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD_MINI }, 78 #if 0 79 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE }, 80 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G }, 81 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS }, 82 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4 }, 83 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4_VZW }, 84 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4S }, 85 { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_5 }, 86 #endif 87 }; 88 89 #define uipad_lookup(v, p) usb_lookup(uipad_devs, v, p) 90 91 static int uipad_match(device_t, cfdata_t, void *); 92 static void uipad_attach(device_t, device_t, void *); 93 static int uipad_detach(device_t, int); 94 95 CFATTACH_DECL_NEW(uipad, sizeof(struct uipad_softc), uipad_match, 96 uipad_attach, uipad_detach, NULL); 97 98 static void 99 uipad_cmd(struct uipad_softc *sc, uint8_t requestType, uint8_t reqno, 100 uint16_t value, uint16_t index) 101 { 102 usb_device_request_t req; 103 usbd_status err; 104 105 DPRINTF(("ipad cmd type=%x, number=%x, value=%d, index=%d\n", 106 requestType, reqno, value, index)); 107 req.bmRequestType = requestType; 108 req.bRequest = reqno; 109 USETW(req.wValue, value); 110 USETW(req.wIndex, index); 111 USETW(req.wLength, 0); 112 113 if ((err = usbd_do_request(sc->sc_udev, &req, NULL)) != 0) 114 aprint_error_dev(sc->sc_dev, "sending command failed %d\n", 115 err); 116 } 117 118 static void 119 uipad_charge(struct uipad_softc *sc) 120 { 121 if (sc->sc_udev->ud_power != USB_MAX_POWER) 122 uipad_cmd(sc, UT_VENDOR | UT_WRITE, 0x40, 0x6400, 0x6400); 123 } 124 125 static int 126 uipad_match(device_t parent, cfdata_t match, void *aux) 127 { 128 struct usb_attach_arg *uaa = aux; 129 130 DPRINTFN(50, ("uipad_match\n")); 131 return uipad_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 132 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 133 } 134 135 static void 136 uipad_attach(device_t parent, device_t self, void *aux) 137 { 138 struct uipad_softc *sc = device_private(self); 139 struct usb_attach_arg *uaa = aux; 140 struct usbd_device * dev = uaa->uaa_device; 141 char *devinfop; 142 143 DPRINTFN(10,("uipad_attach: sc=%p\n", sc)); 144 145 sc->sc_dev = self; 146 sc->sc_udev = dev; 147 148 aprint_naive("\n"); 149 aprint_normal("\n"); 150 151 devinfop = usbd_devinfo_alloc(dev, 0); 152 aprint_normal_dev(self, "%s\n", devinfop); 153 usbd_devinfo_free(devinfop); 154 155 uipad_charge(sc); 156 157 DPRINTFN(10, ("uipad_attach: %p\n", sc->sc_udev)); 158 159 if (!pmf_device_register(self, NULL, NULL)) 160 aprint_error_dev(self, "couldn't establish power handler\n"); 161 162 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 163 return; 164 } 165 166 static int 167 uipad_detach(device_t self, int flags) 168 { 169 struct uipad_softc *sc = device_private(self); 170 DPRINTF(("uipad_detach: sc=%p flags=%d\n", sc, flags)); 171 172 pmf_device_deregister(self); 173 174 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 175 176 return 0; 177 } 178