1
'name iPod Remote Interface
2
'author Daniel M. Story
3
'package iPod Interface
4
'copyright 2007
5
'version 1.0
6
7
Imports System
8
Imports System.IO
9
Imports System.IO.Ports
10
11
Public Class iPodRemoteClass iPodRemote
12
Private WithEvents CommPort As SerialPort
13
14
Public Event PlayButton_Down()
15
Public Event PlayButton_Up()
16
Public Event StopButton_Down()
17
Public Event StopButton_Up()
18
Public Event SkipForwardButton_Down()
19
Public Event SkipForwardButton_Up()
20
Public Event SkipBackwardButton_Down()
21
Public Event SkipBackwardButton_Up()
22
Public Event VolumeUpButton_Down()
23
Public Event VolumeUpButton_Up()
24
Public Event VolumeDownButton_Down()
25
Public Event VolumeDownButton_Up()
26
27
Private LastButton As Short
28
Private buffer As ArrayList
29
30
Public Sub New()Sub New()
31
buffer = New ArrayList
32
CommPort = New SerialPort()
33
CommPort.BaudRate = 19200
34
End Sub
35
36
Public Property Port()Property Port() As String
37
Get
38
Return CommPort.PortName
39
End Get
40
Set(ByVal value As String)
41
CommPort.PortName = value
42
End Set
43
End Property
44
45
Public Sub Open()Sub Open()
46
CommPort.Open()
47
End Sub
48
49
Public Sub Close()Sub Close()
50
CommPort.Close()
51
End Sub
52
53
Private Sub CommPort_DataReceived()Sub CommPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles CommPort.DataReceived
54
Dim i As Integer
55
Dim BufferData() As Byte
56
ReDim BufferData(CommPort.BytesToRead - 1) 'redefine data size to fit entire response
57
If CommPort.Read(BufferData, 0, BufferData.Length) Then
58
For i = 0 To (BufferData.Length - 1)
59
buffer.Add(CByte(BufferData(i)))
60
Next i
61
ParseBuffer()
62
End If
63
End Sub
64
65
Private Sub ParseBuffer()Sub ParseBuffer()
66
'All thanks to: http://ipodlinux.org/Apple_Accessory_Protocol
67
68
Dim Header As Short '= 0xff55 (aka 22015)
69
Dim Length As Byte '= len(mode + command + parameters)
70
Dim Mode As Byte '= command category/mode
71
Dim Command As Short '= command/function
72
Dim Parameter() As Byte '= optional parameter
73
Dim Checksum As Byte '= 0x100 - ( (sum of length, mode, command, and parameters) & 0xFF)
74
75
Dim ParameterLength As Byte
76
ReDim Parameter(0)
77
78
Dim DataSum As Integer '= the datasum to get the checksum
79
Dim MyChecksum As Byte '= the checksum I calculated
80
Dim i As Integer '= for looping
81
Dim offset As Integer
82
83
Do
84
Header = BitConverter.ToInt16(New Byte() {Convert.ToByte(buffer.Item(offset)), Convert.ToByte(buffer.Item(offset + 1))}, 0) 'convert the header to a short (16bit)
85
If Header = 22015 Then 'is the correct header?
86
If (buffer.Count - offset) < 7 Then Exit Do 'safety check
87
Length = Convert.ToByte(buffer.Item(offset + 2))
88
Mode = Convert.ToByte(buffer.Item(offset + 3))
89
Command = BitConverter.ToInt16(New Byte() {Convert.ToByte(buffer.Item(offset + 4)), Convert.ToByte(buffer.Item(offset + 5))}, 0)
90
ParameterLength = Length - 3
91
If (buffer.Count - offset) < 7 + ParameterLength Then Exit Do 'safety check
92
If ParameterLength > 0 Then 'if have parameters (shouldn't matter since the simple remote never sends it)
93
ReDim Parameter(ParameterLength - 1)
94
For i = 0 To (ParameterLength - 1)
95
Parameter(i) = Convert.ToByte(buffer.Item(offset + (i + 5)))
96
Next i
97
End If
98
Checksum = Convert.ToByte(buffer.Item(offset + 6))
99
'all that stuff just separates the data byte array into its categories
100
101
DataSum = 0
102
For i = 2 To Length + 2
103
DataSum += Convert.ToByte(buffer.Item(offset + i))
104
Next i
105
' get the data sum (for calc-ing the sum [up next])
106
107
MyChecksum = &H100 - ((DataSum) And &HFF)
108
'calc the checksum of what was received
109
If MyChecksum = Checksum Then 'check it to see if anythign failed.
110
'Debug.Print(Command.ToString)
111
Select Case Command
112
Case 0
113
'released
114
Raise_LastButton()
115
Case 256
116
'play
117
If LastButton <> 0 Then
118
If LastButton <> Command Then Raise_LastButton()
119
End If
120
If LastButton <> Command Then RaiseEvent PlayButton_Down()
121
Case 512
122
'vol +
123
If LastButton <> 0 Then
124
If LastButton <> Command Then Raise_LastButton()
125
End If
126
If LastButton <> Command Then RaiseEvent VolumeUpButton_Down()
127
Case 1024
128
'vol -
129
If LastButton <> 0 Then
130
If LastButton <> Command Then Raise_LastButton()
131
End If
132
If LastButton <> Command Then RaiseEvent VolumeDownButton_Down()
133
Case 2048
134
'skip >
135
If LastButton <> 0 Then
136
If LastButton <> Command Then Raise_LastButton()
137
End If
138
If LastButton <> Command Then RaiseEvent SkipForwardButton_Down()
139
Case 4096
140
'skip <
141
If LastButton <> 0 Then
142
If LastButton <> Command Then Raise_LastButton()
143
End If
144
If LastButton <> Command Then RaiseEvent SkipBackwardButton_Down()
145
Case -32768
146
'stop
147
If LastButton <> 0 Then
148
If LastButton <> Command Then Raise_LastButton()
149
End If
150
If LastButton <> Command Then RaiseEvent StopButton_Down()
151
End Select
152
LastButton = Command
153
End If
154
For i = 0 To (Length + 2)
155
buffer.RemoveAt(offset)
156
Next i
157
Else
158
offset += 1
159
End If
160
Loop While (offset < (buffer.Count - 1))
161
End Sub
162
163
Private Sub Raise_LastButton()Sub Raise_LastButton()
164
Select Case LastButton
165
Case 256
166
'play
167
RaiseEvent PlayButton_Up()
168
Case 512
169
'vol +
170
RaiseEvent VolumeUpButton_Up()
171
Case 1024
172
'vol -
173
RaiseEvent VolumeDownButton_Up()
174
Case 2048
175
'skip >
176
RaiseEvent SkipForwardButton_Up()
177
Case 4096
178
'skip <
179
RaiseEvent SkipBackwardButton_Up()
180
Case -32768
181
'stop (my remote doesn't have this button, so couldn't test)
182
RaiseEvent StopButton_Up()
183
End Select
184
LastButton = 0
185
End Sub
186
187
Protected Overrides Sub Finalize()Sub Finalize()
188
MyBase.Finalize()
189
If Not CommPort Is Nothing Then If CommPort.IsOpen Then CommPort.Close()
190
CommPort.Dispose()
191
CommPort = Nothing
192
End Sub
193
End Class