I’ve bought cheap USB handset from eBay to use with my VoIP provider. In Widows it worked good with supplied app which supported few VoIP programs and Skype. Since I use Linux on my desktop, I tried to plug it in. In USB listing it showed up as soundcard and HID device.
Bus 001 Device 008: ID 04b4:0307 Cypress Semiconductor Corp.
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x04b4 Cypress Semiconductor Corp.
idProduct 0x0307
bcdDevice 1.10
iManufacturer 0
iProduct 0
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 224
bNumInterfaces 4
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 79
bInCollection 2
baInterfaceNr( 0) 1
baInterfaceNr( 1) 2
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 1
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bNrChannels 2
wChannelConfig 0x0003
Left Front (L)
Right Front (R)
iChannelNames 0
iTerminal 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 3
wTerminalType 0x0301 Speaker
bAssocTerminal 0
bSourceID 2
iTerminal 0
AudioControl Interface Descriptor:
bLength 10
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 2
bSourceID 1
bControlSize 1
bmaControls( 0) 0x03
Mute Control
Volume Control
bmaControls( 1) 0x00
bmaControls( 2) 0x00
iFeature 0
AudioControl Interface Descriptor:
bLength 12
bDescriptorType 36
bDescriptorSubtype 2 (INPUT_TERMINAL)
bTerminalID 5
wTerminalType 0x0201 Microphone
bAssocTerminal 0
bNrChannels 1
wChannelConfig 0x0000
iChannelNames 0
iTerminal 0
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (OUTPUT_TERMINAL)
bTerminalID 7
wTerminalType 0x0101 USB Streaming
bAssocTerminal 0
bSourceID 6
iTerminal 0
AudioControl Interface Descriptor:
bLength 8
bDescriptorType 36
bDescriptorSubtype 6 (FEATURE_UNIT)
bUnitID 6
bSourceID 5
bControlSize 1
bmaControls( 0) 0x03
Mute Control
Volume Control
iFeature 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 1
bDelay 1 frames
wFormatTag 1 PCM
AudioStreaming Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 2
bSubframeSize 2
bBitResolution 16
bSamFreqType 1 Discrete
tSamFreq[ 0] 48000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 9
Transfer Type Isochronous
Synch Type Adaptive
Usage Type Data
wMaxPacketSize 0x00c0 1x 192 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioControl Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x00
bLockDelayUnits 0 Undefined
wLockDelay 0 Undefined
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 1
bNumEndpoints 1
bInterfaceClass 1 Audio
bInterfaceSubClass 2 Streaming
bInterfaceProtocol 0
iInterface 0
AudioStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (AS_GENERAL)
bTerminalLink 7
bDelay 1 frames
wFormatTag 1 PCM
AudioStreaming Interface Descriptor:
bLength 11
bDescriptorType 36
bDescriptorSubtype 2 (FORMAT_TYPE)
bFormatType 1 (FORMAT_TYPE_I)
bNrChannels 1
bSubframeSize 2
bBitResolution 16
bSamFreqType 1 Discrete
tSamFreq[ 0] 8000
Endpoint Descriptor:
bLength 9
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 1
Transfer Type Isochronous
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 1
bRefresh 0
bSynchAddress 0
AudioControl Endpoint Descriptor:
bLength 7
bDescriptorType 37
bDescriptorSubtype 1 (EP_GENERAL)
bmAttributes 0x00
bLockDelayUnits 0 Undefined
wLockDelay 0 Undefined
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 36
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 48
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0020 1x 32 bytes
bInterval 1
Soundcard was working out of box: headset speaker and mic were correctly working when set in my linphone SIP client. But I also wanted to utilize phones keyboard and display. I checked which /dev/hidrawX device corresponds to my phone and started
sudo cat /dev/hidraw1 | hexdump. When I pressed buttons, following output has appeared:
#sudo cat /dev/hidraw1 | hexdump 0000000 0301 0100 0101 0101 0001 0100 0101 0101 0000010 0901 0100 0101 0101 0001 0100 0101 0101 0000020 0f01 0100 0101 0101 0001 0100 0101 0101 0000030 0401 0100 0101 0101 0001 0100 0101 0101 0000040 0a01 0100 0101 0101 0001 0100 0101 0101 0000050 1001 0100 0101 0101 0001 0100 0101 0101 0000060 0501 0100 0101 0101 0001 0100 0101 0101 0000070 0b01 0100 0101 0101 0001 0100 0101 0101 0000080 1101 0100 0101 0101 0001 0100 0101 0101
Good! One line for each button press. So I created a short python script to open /dev/hidraw1, read inputs, then map it to keys and print to stdout and it worked great!
#!/usr/bin/python
keys = {
0x00 : "",
0x03 : "1",
0x09 : "2",
0x0f : "3",
0x04 : "4",
0x0a : "5",
0x10 : "6",
0x05 : "7",
0x0b : "8",
0x11 : "9",
0x06 : "*",
0x0c : "0",
0x12 : "#",
0x02 : "yes",
0x08 : "S",
0x0e : "no",
0x01 : "left",
0x13 : "up",
0x16 : "down",
0x0d : "right",
0x19 : "vol+",
0x1c : "vol-",
0x1b : "mute",
}
file = open( "/dev/hidraw1", "w+b" );
def getKey():
buf = file.read(8)
return keys[ord(buf[1])]
while( 1 ):
k = getKey();
print k
file.close();
Next mission was to make the display work. My assumption was, that it will also communicate through hidraw device. So I fired dd if=/dev/urandom of=/dev/hidraw1 and YES! Time to time the display blinked or showed some messy pixel block.
So I returned back to windows. I fired up usbsnoop to see what does the original software send to update screen. I found out, that it sends many blocks in form:
0x0301XXYYZZZZZZZZZZZZZZZZZZZZZZX’s and Y’s were incrementing independently and Z’s were apparently some data. I experimented with sending 0x0301XXYYFFFFFFFFFFFFFFFFFFFFFF with various X’s and Y’s like this:
buf="0301".decode("hex")+chr(x)+chr(y)+"ffffffffffffffffffffff".decode("hex")
file.write(buf)
Some of them were written to display as full black blocks and some were not. I spent some time experimenting what’s wrong after I found out, that I have to file.flush() after writing each block.
Afer this, I was able to successfully write any block on the screen. In following code you can check exactly how.
#!/usr/bin/python
import struct
import Image, ImageDraw, ImageFont
import time
keys = {
0x00 : "",
0x03 : "1",
0x09 : "2",
0x0f : "3",
0x04 : "4",
0x0a : "5",
0x10 : "6",
0x05 : "7",
0x0b : "8",
0x11 : "9",
0x06 : "*",
0x0c : "0",
0x12 : "#",
0x02 : "yes",
0x08 : "S",
0x0e : "no",
0x01 : "left",
0x13 : "up",
0x16 : "down",
0x0d : "right",
0x19 : "vol+",
0x1c : "vol-",
0x1b : "mute",
}
file = open( "/dev/hidraw1", "w+b" );
def getKey():
buf = file.read(8)
return keys[ord(buf[1])]
def paint():
pixels = img.load() # create the pixel map
pixels = img.transpose(Image.ROTATE_180).load() # create the pixel map
b = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for r in range(0, 8):
for s in range (0, 12):
for i in range (0, 12):
b[i] = 0
for j in range (0, 8):
if (pixels[i + 12 * s, j + 8 * r] < 128):
b[i] |= 2**j
buf="0301".decode("hex")+chr(r)+chr(s*11)+chr(b[0])+chr(b[1])+chr(b[2])+chr(b[3])+chr(b[4])+chr(b[5])+chr(b[6])+chr(b[7])+chr(b[8])+chr(b[9])+chr(b[10])+chr(b[11])
file.write(buf)
file.flush()
def drawText(text):
draw.text((0, 0), drawText.old , 255, font=font)
draw.text((0, 0), text , 0, font=font)
drawText.old = text
paint()
drawText.old = ""
img = Image.new( '1', (144,64), "white")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("/usr/share/fonts/truetype/msttcorefonts/arial.ttf", 20)
text = ""
# draw logo into canvas
logo = Image.open("logo.png").convert("1")
img.paste(logo, (0,0))
# write canvas to display
paint()
# clear canvas
draw.rectangle((0,0,142,63), fill=255)
while( 1 ):
k = getKey();
if (k == ""):
0
elif (k == "no"):
text = ""
drawText(text)
elif (k == "yes"):
text = ""
drawText("calling...")
else:
text = text + k
drawText(text)
# img.show()
file.close();
Note: Displays first pixel is in the lower right corner, so when displaying things, you have to rotate image 180°.
I know that all this can possibly be found in phones chip documentation but this way it was definitely more fun.
Meanwhile I stopped using VoIP services so my motivation to integrate this with some VoIP phone is gone :). Feel free to finish this and share.
To end up, I attach some photos.





This was a very interesting post. I have a similar product but without the display.
Will try to hack it and use it with internal asterisk server.
Interesting. Does it work with Android 5.0+ phones as usb headset?
I have idea to make GSM phone gate way. Check it out, you may like it.
https://github.com/axet/android-gsm-gate
Hi,
I don’t see the benefit of using Android phone. Why not use USB 3G/4G dongle with SIM?
https://github.com/bg111/asterisk-chan-dongle
Use of an Android Tablet would allow many SIP apps. A USB phone connected to the Android tablet would allow a physical handset for those that want it.