/* * 15. Oct. 2008 - Now with iPod touch/iPhone support */ /* * Copyright (c) 2008, Henrik 'hrkfrd' Friedrichsen * http://50hz.ws * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the company nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * This is to retrieve the iSerialNumber string, needed by libgpod to generate a valid iTunesDB * for some iPod models. * Simply provide the usb bus (e.g. /dev/usb1) your iPod is attached to. */ #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #endif int get_desc(int fd, int addr, int type, int index, int len, void* buf, int langid) { struct usb_ctl_request req; memset(&req, 0, sizeof(struct usb_ctl_request)); memset(&req.ucr_request, 0, sizeof(usb_device_request_t)); req.ucr_request.bmRequestType = UT_READ_DEVICE; req.ucr_request.bRequest = UR_GET_DESCRIPTOR; USETW2(req.ucr_request.wValue, type, index); USETW(req.ucr_request.wIndex, langid); USETW(req.ucr_request.wLength, len); req.ucr_addr = addr; req.ucr_data = buf; req.ucr_flags = USBD_SHORT_XFER_OK; if(ioctl(fd, USB_REQUEST, &req)) { fprintf(stderr, "error in get_desc(): %s\n", strerror(errno)); return 0; } return req.ucr_actlen; } void dumpdev(int fd, int addr) { int langid = 0; struct usb_device_info di; unsigned i; char* s, *buf; usb_device_descriptor_t dd; usb_string_descriptor_t sd; memset(&di, 0, sizeof(struct usb_device_info)); memset(&dd, 0, sizeof(usb_device_descriptor_t)); memset(&sd, 0, sizeof(usb_string_descriptor_t)); di.udi_addr = addr; if(ioctl(fd, USB_DEVICEINFO, &di)) { close(fd); exit(EXIT_FAILURE); } if(di.udi_vendorNo != 0x05ac) // dunno if udi_productNo changes depending on the ipod model, so vendor check should suffice return; printf("[%i:%i] %s - %s\n", di.udi_bus, di.udi_addr, di.udi_vendor, di.udi_product); get_desc(fd, addr, UDESC_DEVICE, 0, USB_DEVICE_DESCRIPTOR_SIZE, (void*)&dd, 0); i = get_desc(fd, addr, UDESC_STRING, USB_LANGUAGE_TABLE, sizeof(usb_string_descriptor_t), &sd, 0); if(i >= 4) { langid = UGETW(sd.bString[0]); } get_desc(fd, addr, UDESC_STRING, dd.iSerialNumber, 2, (void*)&sd, langid); get_desc(fd, addr, UDESC_STRING, dd.iSerialNumber, sd.bLength, (void*)&sd, langid); s = buf = malloc(sd.bLength); for(i = 0; i < sd.bLength; i++) { char c = UGETW(sd.bString[i]); if((c & 0xff00) == 0) *s++ = c; else if((c & 0x00f) == 0) *s++ = c >> 8; else *s++ = '?'; } *s++ = 0; printf("iSerialNumber: %s\n", buf); free(buf); } int main(int argc, char* argv[]) { unsigned i; if(argc < 2) { fprintf(stderr, "usage: %s \n", argv[0]); return EXIT_FAILURE; } int fd = open(argv[1], O_RDONLY); if(fd == -1) { fprintf(stderr, "could not open %s (%s)\n", argv[1], strerror(errno)); return EXIT_FAILURE; } for(i = 1; i < USB_MAX_DEVICES; i++) dumpdev(fd, i); close(fd); }