1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006-2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
27 #include <sys/types.h>
29 #include <sys/ioctl.h>
34 #if defined(linux) || defined (__linux)
35 #include <sys/mount.h>
36 #include <linux/hdreg.h>
37 #include <scsi/scsi_ioctl.h>
40 #define IPOD_SECTORSIZE_IOCTL BLKSSZGET
42 static void get_geometry(struct ipod_t
* ipod
)
44 struct hd_geometry geometry
;
46 if (!ioctl(ipod
->dh
, HDIO_GETGEO
, &geometry
)) {
47 /* never use geometry.cylinders - it is truncated */
48 ipod
->num_heads
= geometry
.heads
;
49 ipod
->sectors_per_track
= geometry
.sectors
;
52 ipod
->sectors_per_track
= 0;
56 /* Linux SCSI Inquiry code based on the documentation and example code from
57 http://www.ibm.com/developerworks/linux/library/l-scsi-api/index.html
60 int ipod_scsi_inquiry(struct ipod_t
* ipod
, int page_code
,
61 unsigned char* buf
, int bufsize
)
65 unsigned char sense_buffer
[255];
67 memset(&hdr
, 0, sizeof(hdr
));
69 hdr
.interface_id
= 'S'; /* this is the only choice we have! */
70 hdr
.flags
= SG_FLAG_LUN_INHIBIT
; /* this would put the LUN to 2nd byte of cdb*/
74 hdr
.dxfer_len
= bufsize
;
77 hdr
.sbp
= sense_buffer
;
78 hdr
.mx_sb_len
= sizeof(sense_buffer
);
80 /* Set the cdb format */
82 cdb
[1] = 1; /* Enable Vital Product Data (EVPD) */
83 cdb
[2] = page_code
& 0xff;
86 cdb
[5] = 0; /* For control filed, just use 0 */
88 hdr
.dxfer_direction
= SG_DXFER_FROM_DEV
;
92 int ret
= ioctl(ipod
->dh
, SG_IO
, &hdr
);
101 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
102 || defined(__bsdi__) || defined(__DragonFly__)
103 #include <sys/disk.h>
104 #define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE
106 /* TODO: Implement this function for BSD */
107 static void get_geometry(struct ipod_t
* ipod
)
109 /* Are these universal for all ipods? */
110 ipod
->num_heads
= 255;
111 ipod
->sectors_per_track
= 63;
114 int ipod_scsi_inquiry(struct ipod_t
* ipod
, int page_code
,
115 unsigned char* buf
, int bufsize
)
117 /* TODO: Implement for BSD */
121 #elif defined(__APPLE__) && defined(__MACH__)
122 #include <sys/disk.h>
123 #define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
125 /* TODO: Implement this function for Mac OS X */
126 static void get_geometry(struct ipod_t
* ipod
)
128 /* Are these universal for all ipods? */
129 ipod
->num_heads
= 255;
130 ipod
->sectors_per_track
= 63;
133 int ipod_scsi_inquiry(struct ipod_t
* ipod
, int page_code
,
134 unsigned char* buf
, int bufsize
)
136 /* TODO: Implement for OS X */
141 #error No sector-size detection implemented for this platform
144 #if defined(__APPLE__) && defined(__MACH__)
145 static int ipod_unmount(struct ipod_t
* ipod
)
150 sprintf(cmd
, "/usr/sbin/diskutil unmount \"%ss2\"",ipod
->diskname
);
151 fprintf(stderr
,"[INFO] ");
157 perror("Unmount failed");
163 void print_error(char* msg
)
168 int ipod_open(struct ipod_t
* ipod
, int silent
)
170 ipod
->dh
=open(ipod
->diskname
,O_RDONLY
);
172 if (!silent
) perror(ipod
->diskname
);
173 if(errno
== EACCES
) return -2;
177 /* Read information about the disk */
179 if(ioctl(ipod
->dh
,IPOD_SECTORSIZE_IOCTL
,&ipod
->sector_size
) < 0) {
180 ipod
->sector_size
=512;
182 fprintf(stderr
,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n"
193 int ipod_reopen_rw(struct ipod_t
* ipod
)
195 #if defined(__APPLE__) && defined(__MACH__)
196 if (ipod_unmount(ipod
) < 0)
201 ipod
->dh
=open(ipod
->diskname
,O_RDWR
);
203 perror(ipod
->diskname
);
209 int ipod_close(struct ipod_t
* ipod
)
215 int ipod_alloc_buffer(unsigned char** sectorbuf
, int bufsize
)
217 *sectorbuf
=malloc(bufsize
);
218 if (*sectorbuf
== NULL
) {
224 int ipod_seek(struct ipod_t
* ipod
, unsigned long pos
)
228 res
= lseek(ipod
->dh
, pos
, SEEK_SET
);
236 ssize_t
ipod_read(struct ipod_t
* ipod
, unsigned char* buf
, int nbytes
)
238 return read(ipod
->dh
, buf
, nbytes
);
241 ssize_t
ipod_write(struct ipod_t
* ipod
, unsigned char* buf
, int nbytes
)
243 return write(ipod
->dh
, buf
, nbytes
);