我下载的是barry-0.11的源代码,其main函数位于/barry-0.11/tools/bcharge.cc中,主函数基本逻辑如下:
int main(int argc, char *argv[])
{
struct usb_bus *busses;
...
usb_init();
...
busses = usb_get_busses();
...
for( bus = busses; bus; bus = bus->next ) {
...
for (dev = bus->devices; dev; dev = dev->next) {
// Is this a blackberry?
if( dev->descriptor.idVendor == VENDOR_RIM ) {
switch(dev->descriptor.idProduct)
{
case PRODUCT_RIM_BLACKBERRY:
if( !process(dev, false) )
resume();
break;
case PRODUCT_RIM_PEARL_DUAL:
case PRODUCT_RIM_PEARL:
if( !process(dev, true) )
resume();
break;
}
}
}
}
}
很显然我们关注的东西都在process函数里面:
bool process(struct usb_device *dev, bool is_pearl)
{
...
// open
usb_dev_handle *handle = usb_open(dev);
// adjust power
if( dev->config &&
dev->descriptor.bNumConfigurations >= 1 &&
dev->config[0].MaxPower < 250 )
{
charge(handle);
apply = true;
}
...
// apply changes
if( apply ) {
if( usb_set_configuration(handle, BLACKBERRY_CONFIGURATION) < 0 )
driver_conflict(handle);
...
}
// cleanup
usb_close(handle);
...
}
int main(int argc, char *argv[])
{
struct usb_bus *busses;
...
usb_init();
...
busses = usb_get_busses();
...
for( bus = busses; bus; bus = bus->next ) {
...
for (dev = bus->devices; dev; dev = dev->next) {
// Is this a blackberry?
if( dev->descriptor.idVendor == VENDOR_RIM ) {
switch(dev->descriptor.idProduct)
{
case PRODUCT_RIM_BLACKBERRY:
if( !process(dev, false) )
resume();
break;
case PRODUCT_RIM_PEARL_DUAL:
case PRODUCT_RIM_PEARL:
if( !process(dev, true) )
resume();
break;
}
}
}
}
}
很显然我们关注的东西都在process函数里面:
bool process(struct usb_device *dev, bool is_pearl)
{
...
// open
usb_dev_handle *handle = usb_open(dev);
// adjust power
if( dev->config &&
dev->descriptor.bNumConfigurations >= 1 &&
dev->config[0].MaxPower < 250 )
{
charge(handle);
apply = true;
}
...
// apply changes
if( apply ) {
if( usb_set_configuration(handle, BLACKBERRY_CONFIGURATION) < 0 )
driver_conflict(handle);
...
}
// cleanup
usb_close(handle);
...
}
Sending two magic commands and then set the configuration. The device will then reset itself with the new power usage and should start charging.
charge函数看起来是向USB那头的Blackberry设备发去了一些特殊指令,这是导致充电的关键指令。
void charge(struct usb_dev_handle *handle)
{
// the special sauce... these steps seem to do the trick
// for the 7750 series... needs testing on others
char buffer[2];
control(handle, 0xc0, 0xa5, 0, 1, buffer, 2, 100);
control(handle, 0x40, 0xa2, 0, 1, buffer, 0, 100);
}
control是 usb_control_msg的简单封装(在这个case中看起来没有必要),其函数原型如下:
usb_control_msg
Name
usb_control_msg -- Send a control message to a device
Description
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
usb_control_msg performs a control request to the default control pipe on a device. The parameters mirror the types of the same name in the USB specification. Returns number of bytes written/read or < 0 on error.
void charge(struct usb_dev_handle *handle)
{
// the special sauce... these steps seem to do the trick
// for the 7750 series... needs testing on others
char buffer[2];
control(handle, 0xc0, 0xa5, 0, 1, buffer, 2, 100);
control(handle, 0x40, 0xa2, 0, 1, buffer, 0, 100);
}
control是 usb_control_msg的简单封装(在这个case中看起来没有必要),其函数原型如下:
usb_control_msg
Name
usb_control_msg -- Send a control message to a device
Description
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
usb_control_msg performs a control request to the default control pipe on a device. The parameters mirror the types of the same name in the USB specification. Returns number of bytes written/read or < 0 on error.
该函数的参数和USB Specification是一一对应的:
USB Spec BCharge Meaning
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bmRequestType requesttype determine the direction of the request, type of request and designated recipient.
bRequest request determine the request being made
wValue bytes ...
wIndex index The wValue and wIndex fields allow parameters to be passed with the request
wLength size wLength is used the specify the number of bytes to be transferred should there be a data phase
timeout time to wait for the message to complete before timing out (if 0 the wait is forever)
按照USB 2.0 Specification(Chapter 9 USB Device Framework,->9.3 USB Device Requests),bmRequestType的各个bit意义如下:
D7 Data Phase Transfer Direction
0 = Host to Device
1 = Device to Host
D6..5 Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved
D4..0 Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other
4..31 = Reserved
0 = Host to Device
1 = Device to Host
D6..5 Type
0 = Standard
1 = Class
2 = Vendor
3 = Reserved
D4..0 Recipient
0 = Device
1 = Interface
2 = Endpoint
3 = Other
4..31 = Reserved
0xc0就是1100,0000 - Device to host,也就是读,Type是Vendor,Recipient是Device
0x40就是0100,0000 - Host to device,也就是写,Type是Vendor,Recipient是Device
bRequest(0xa5,0xa2)看起来是Blackberry特有的命令了,我花了半天时间也没查到关于这两个命令的、有用的线索。悬念依旧......
==================================================================
Reference:
uberry: The uberry driver first appeared in OpenBSD 4.1. It provides the most minimal support for the USB-connected Research In Motion Blackberry devices, permitting them to be charged and powered from a USB port.