blob: c62e0c827562c93190d645897788a92f26ed5f4f [file] [log] [blame]
Dave Chapman4b7e1e02006-12-13 09:02:18 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Dave Chapmane332f4c2007-02-05 01:20:20 +000010 * Copyright (C) 2006-2007 Dave Chapman
Dave Chapman4b7e1e02006-12-13 09:02:18 +000011 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <unistd.h>
22#include <fcntl.h>
23#include <string.h>
24#include <stdlib.h>
25#include <sys/types.h>
26#include <sys/stat.h>
Dave Chapman8280c8c2006-12-13 20:26:44 +000027#include <sys/ioctl.h>
Dominik Riebeling194b2ca2008-05-04 11:59:04 +000028#include <errno.h>
Dave Chapman8280c8c2006-12-13 20:26:44 +000029
Dave Chapman56780e32007-06-16 22:32:57 +000030#include "ipodio.h"
31
Dave Chapman8280c8c2006-12-13 20:26:44 +000032#if defined(linux) || defined (__linux)
Dave Chapman49e016c2006-12-15 00:09:48 +000033#include <sys/mount.h>
Dave Chapman56780e32007-06-16 22:32:57 +000034#include <linux/hdreg.h>
Dave Chapman49e016c2006-12-15 00:09:48 +000035#define IPOD_SECTORSIZE_IOCTL BLKSSZGET
Dave Chapman56780e32007-06-16 22:32:57 +000036
37static void get_geometry(struct ipod_t* ipod)
38{
39 struct hd_geometry geometry;
40
41 if (!ioctl(ipod->dh, HDIO_GETGEO, &geometry)) {
42 /* never use geometry.cylinders - it is truncated */
43 ipod->num_heads = geometry.heads;
44 ipod->sectors_per_track = geometry.sectors;
45 } else {
46 ipod->num_heads = 0;
47 ipod->sectors_per_track = 0;
48 }
49}
50
Dave Chapman8280c8c2006-12-13 20:26:44 +000051#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
52 || defined(__bsdi__) || defined(__DragonFly__)
Dave Chapman49e016c2006-12-15 00:09:48 +000053#include <sys/disk.h>
54#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE
Dave Chapman56780e32007-06-16 22:32:57 +000055
56/* TODO: Implement this function for BSD */
57static void get_geometry(struct ipod_t* ipod)
58{
59 /* Are these universal for all ipods? */
60 ipod->num_heads = 255;
61 ipod->sectors_per_track = 63;
62}
63
Dave Chapman8280c8c2006-12-13 20:26:44 +000064#elif defined(__APPLE__) && defined(__MACH__)
Dave Chapman49e016c2006-12-15 00:09:48 +000065#include <sys/disk.h>
66#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
Dave Chapman56780e32007-06-16 22:32:57 +000067
68/* TODO: Implement this function for Mac OS X */
69static void get_geometry(struct ipod_t* ipod)
70{
71 /* Are these universal for all ipods? */
72 ipod->num_heads = 255;
73 ipod->sectors_per_track = 63;
74}
75
Dave Chapman8280c8c2006-12-13 20:26:44 +000076#else
77 #error No sector-size detection implemented for this platform
78#endif
Dave Chapman4b7e1e02006-12-13 09:02:18 +000079
Dave Chapmanf225f042007-09-01 22:55:37 +000080#if defined(__APPLE__) && defined(__MACH__)
81static int ipod_unmount(struct ipod_t* ipod)
82{
83 char cmd[4096];
84 int res;
85
86 sprintf(cmd, "/usr/sbin/diskutil unmount \"%ss2\"",ipod->diskname);
87 fprintf(stderr,"[INFO] ");
88 res = system(cmd);
89
90 if (res==0) {
91 return 0;
92 } else {
93 perror("Unmount failed");
94 return -1;
95 }
96}
97#endif
98
Dave Chapman4b7e1e02006-12-13 09:02:18 +000099void print_error(char* msg)
100{
101 perror(msg);
102}
103
Dave Chapman31aa4522007-02-04 11:42:11 +0000104int ipod_open(struct ipod_t* ipod, int silent)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000105{
Dave Chapman31aa4522007-02-04 11:42:11 +0000106 ipod->dh=open(ipod->diskname,O_RDONLY);
107 if (ipod->dh < 0) {
108 if (!silent) perror(ipod->diskname);
Dominik Riebeling194b2ca2008-05-04 11:59:04 +0000109 if(errno == EACCES) return -2;
110 else return -1;
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000111 }
112
Dave Chapman56780e32007-06-16 22:32:57 +0000113 /* Read information about the disk */
114
Dave Chapman31aa4522007-02-04 11:42:11 +0000115 if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) {
116 ipod->sector_size=512;
117 if (!silent) {
118 fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n"
119 ,ipod->sector_size);
120 }
Dave Chapman8280c8c2006-12-13 20:26:44 +0000121 }
Dave Chapman56780e32007-06-16 22:32:57 +0000122
123 get_geometry(ipod);
124
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000125 return 0;
126}
127
128
Dave Chapman31aa4522007-02-04 11:42:11 +0000129int ipod_reopen_rw(struct ipod_t* ipod)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000130{
Dave Chapmanf225f042007-09-01 22:55:37 +0000131#if defined(__APPLE__) && defined(__MACH__)
132 if (ipod_unmount(ipod) < 0)
133 return -1;
134#endif
135
Dave Chapman31aa4522007-02-04 11:42:11 +0000136 close(ipod->dh);
137 ipod->dh=open(ipod->diskname,O_RDWR);
138 if (ipod->dh < 0) {
139 perror(ipod->diskname);
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000140 return -1;
141 }
142 return 0;
143}
144
Dave Chapman31aa4522007-02-04 11:42:11 +0000145int ipod_close(struct ipod_t* ipod)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000146{
Dave Chapman31aa4522007-02-04 11:42:11 +0000147 close(ipod->dh);
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000148 return 0;
149}
150
151int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize)
152{
153 *sectorbuf=malloc(bufsize);
154 if (*sectorbuf == NULL) {
155 return -1;
156 }
157 return 0;
158}
159
Dave Chapman31aa4522007-02-04 11:42:11 +0000160int ipod_seek(struct ipod_t* ipod, unsigned long pos)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000161{
162 off_t res;
163
Dave Chapman31aa4522007-02-04 11:42:11 +0000164 res = lseek(ipod->dh, pos, SEEK_SET);
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000165
166 if (res == -1) {
167 return -1;
168 }
169 return 0;
170}
171
Dave Chapman2cc80f52007-07-29 21:19:14 +0000172ssize_t ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000173{
Dave Chapman31aa4522007-02-04 11:42:11 +0000174 return read(ipod->dh, buf, nbytes);
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000175}
176
Dave Chapman2cc80f52007-07-29 21:19:14 +0000177ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000178{
Dave Chapman31aa4522007-02-04 11:42:11 +0000179 return write(ipod->dh, buf, nbytes);
Dave Chapman4b7e1e02006-12-13 09:02:18 +0000180}