Switch link speed unit to bit/s to support low bitrate speed too
(hello slow dialup line...) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39581 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -37,7 +37,7 @@ typedef struct ether_address {
|
|||||||
typedef struct ether_link_state {
|
typedef struct ether_link_state {
|
||||||
uint32 media; /* as specified in net/if_media.h */
|
uint32 media; /* as specified in net/if_media.h */
|
||||||
uint32 quality; /* in one tenth of a percent */
|
uint32 quality; /* in one tenth of a percent */
|
||||||
uint64 speed; /* in Kbit/s */
|
uint64 speed; /* in bit/s */
|
||||||
} ether_link_state_t;
|
} ether_link_state_t;
|
||||||
|
|
||||||
#endif /* _ETHER_DRIVER_H */
|
#endif /* _ETHER_DRIVER_H */
|
||||||
|
|||||||
@@ -280,11 +280,11 @@ b44_ioctl(void *cookie,uint32 op, void *data, size_t len)
|
|||||||
switch (pUmDevice->lm_dev.LineSpeed) {
|
switch (pUmDevice->lm_dev.LineSpeed) {
|
||||||
case LM_LINE_SPEED_10MBPS:
|
case LM_LINE_SPEED_10MBPS:
|
||||||
state.media |= IFM_10_T;
|
state.media |= IFM_10_T;
|
||||||
state.speed = 10000;
|
state.speed = 10000000;
|
||||||
break;
|
break;
|
||||||
case LM_LINE_SPEED_100MBPS:
|
case LM_LINE_SPEED_100MBPS:
|
||||||
state.media |= IFM_100_TX;
|
state.media |= IFM_100_TX;
|
||||||
state.speed = 100000;
|
state.speed = 100000000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state.speed = 0;
|
state.speed = 0;
|
||||||
|
|||||||
@@ -509,15 +509,15 @@ b57_ioctl(void *cookie,uint32 op,void *data,size_t len)
|
|||||||
switch (pUmDevice->lm_dev.LineSpeed) {
|
switch (pUmDevice->lm_dev.LineSpeed) {
|
||||||
case LM_LINE_SPEED_10MBPS:
|
case LM_LINE_SPEED_10MBPS:
|
||||||
state.media |= IFM_10_T;
|
state.media |= IFM_10_T;
|
||||||
state.speed = 10000;
|
state.speed = 10000000;
|
||||||
break;
|
break;
|
||||||
case LM_LINE_SPEED_100MBPS:
|
case LM_LINE_SPEED_100MBPS:
|
||||||
state.media |= IFM_100_TX;
|
state.media |= IFM_100_TX;
|
||||||
state.speed = 100000;
|
state.speed = 100000000;
|
||||||
break;
|
break;
|
||||||
case LM_LINE_SPEED_1000MBPS:
|
case LM_LINE_SPEED_1000MBPS:
|
||||||
state.media |= IFM_1000_T;
|
state.media |= IFM_1000_T;
|
||||||
state.speed = 1000000;
|
state.speed = 1000000000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
state.speed = 0;
|
state.speed = 0;
|
||||||
|
|||||||
@@ -375,11 +375,11 @@ ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
|
|||||||
if (mediareq.ifm_status & IFM_ACTIVE)
|
if (mediareq.ifm_status & IFM_ACTIVE)
|
||||||
state.media |= IFM_ACTIVE;
|
state.media |= IFM_ACTIVE;
|
||||||
if (mediareq.ifm_active & IFM_10_T)
|
if (mediareq.ifm_active & IFM_10_T)
|
||||||
state.speed = 10000;
|
state.speed = 10000000;
|
||||||
else if (mediareq.ifm_active & IFM_100_TX)
|
else if (mediareq.ifm_active & IFM_100_TX)
|
||||||
state.speed = 100000;
|
state.speed = 100000000;
|
||||||
else
|
else
|
||||||
state.speed = 1000000;
|
state.speed = 1000000000;
|
||||||
state.quality = 1000;
|
state.quality = 1000;
|
||||||
|
|
||||||
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
|
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
|
||||||
|
|||||||
@@ -974,11 +974,11 @@ rtl8169_control(void *cookie, uint32 op, void *arg, size_t len)
|
|||||||
state.media = IFM_ETHER;
|
state.media = IFM_ETHER;
|
||||||
state.media |= (device->link_ok ? IFM_ACTIVE : 0);
|
state.media |= (device->link_ok ? IFM_ACTIVE : 0);
|
||||||
state.media |= (device->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX);
|
state.media |= (device->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX);
|
||||||
if (device->speed == 1000000)
|
if (device->speed == 1000000000)
|
||||||
state.media |= IFM_1000_T;
|
state.media |= IFM_1000_T;
|
||||||
else if (device->speed == 100000)
|
else if (device->speed == 100000000)
|
||||||
state.media |= IFM_100_TX;
|
state.media |= IFM_100_TX;
|
||||||
else if (device->speed == 10000)
|
else if (device->speed == 10000000)
|
||||||
state.media |= IFM_10_T;
|
state.media |= IFM_10_T;
|
||||||
|
|
||||||
state.speed = device->speed;
|
state.speed = device->speed;
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ device_ioctl(void *data, uint32 msg, void *buffer, size_t bufferLength)
|
|||||||
| (info->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX)
|
| (info->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX)
|
||||||
| (info->speed == LINK_SPEED_100_MBIT ? IFM_100_TX : IFM_10_T);
|
| (info->speed == LINK_SPEED_100_MBIT ? IFM_100_TX : IFM_10_T);
|
||||||
state.speed = info->speed == LINK_SPEED_100_MBIT
|
state.speed = info->speed == LINK_SPEED_100_MBIT
|
||||||
? 100000 : 10000;
|
? 100000000 : 10000000;
|
||||||
state.quality = 1000;
|
state.quality = 1000;
|
||||||
|
|
||||||
return user_memcpy(buffer, &state, sizeof(ether_link_state_t));
|
return user_memcpy(buffer, &state, sizeof(ether_link_state_t));
|
||||||
|
|||||||
@@ -264,11 +264,11 @@ AX88172Device::GetLinkState(ether_link_state *linkState)
|
|||||||
linkState->media |= mediumStatus & (ANLPAR_TX_FD | ANLPAR_10_FD) ?
|
linkState->media |= mediumStatus & (ANLPAR_TX_FD | ANLPAR_10_FD) ?
|
||||||
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
||||||
|
|
||||||
linkState->speed = mediumStatus & (ANLPAR_TX_FD | ANLPAR_TX_HD) ? 100000 : 10000;
|
linkState->speed = mediumStatus & (ANLPAR_TX_FD | ANLPAR_TX_HD) ? 100000000 : 10000000;
|
||||||
|
|
||||||
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
||||||
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
||||||
linkState->speed / 1000,
|
linkState->speed,
|
||||||
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -405,13 +405,13 @@ AX88178Device::GetLinkState(ether_link_state *linkState)
|
|||||||
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
|
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
|
||||||
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
||||||
|
|
||||||
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000 : 10000;
|
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000000 : 10000000;
|
||||||
linkState->speed = (mediumStatus & MEDIUM_STATE_GM) ?
|
linkState->speed = (mediumStatus & MEDIUM_STATE_GM) ?
|
||||||
1000000 : linkState->speed;
|
1000000000 : linkState->speed;
|
||||||
|
|
||||||
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
||||||
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
||||||
linkState->speed / 1000,
|
linkState->speed,
|
||||||
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,11 +382,11 @@ AX88772Device::GetLinkState(ether_link_state *linkState)
|
|||||||
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
|
linkState->media |= (mediumStatus & MEDIUM_STATE_FD) ?
|
||||||
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
IFM_FULL_DUPLEX : IFM_HALF_DUPLEX;
|
||||||
|
|
||||||
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000 : 10000;
|
linkState->speed = (mediumStatus & MEDIUM_STATE_PS_100) ? 100000000 : 10000000;
|
||||||
|
|
||||||
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
||||||
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
||||||
linkState->speed / 1000,
|
linkState->speed,
|
||||||
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -815,9 +815,9 @@ DavicomDevice::GetLinkState(ether_link_state *linkState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (registerValue & NSR_SPEED)
|
if (registerValue & NSR_SPEED)
|
||||||
linkState->speed = 10000;
|
linkState->speed = 10000000;
|
||||||
else
|
else
|
||||||
linkState->speed = 100000;
|
linkState->speed = 100000000;
|
||||||
|
|
||||||
linkState->quality = 1000;
|
linkState->quality = 1000;
|
||||||
|
|
||||||
@@ -841,7 +841,7 @@ DavicomDevice::GetLinkState(ether_link_state *linkState)
|
|||||||
|
|
||||||
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
TRACE_FLOW("Medium state: %s, %lld MBit/s, %s duplex.\n",
|
||||||
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
(linkState->media & IFM_ACTIVE) ? "active" : "inactive",
|
||||||
linkState->speed / 1000,
|
linkState->speed,
|
||||||
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
(linkState->media & IFM_FULL_DUPLEX) ? "full" : "half");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ ECMDevice::Control(uint32 op, void *buffer, size_t length)
|
|||||||
state->media = IFM_ETHER | IFM_FULL_DUPLEX
|
state->media = IFM_ETHER | IFM_FULL_DUPLEX
|
||||||
| (fHasConnection ? IFM_ACTIVE : 0);
|
| (fHasConnection ? IFM_ACTIVE : 0);
|
||||||
state->quality = 1000;
|
state->quality = 1000;
|
||||||
state->speed = fDownstreamSpeed / 1000;
|
state->speed = fDownstreamSpeed;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ struct dialup_device : net_device {
|
|||||||
int fd;
|
int fd;
|
||||||
struct termios line_config;
|
struct termios line_config;
|
||||||
dialup_state state;
|
dialup_state state;
|
||||||
|
bool data_mode;
|
||||||
char init_string[64];
|
char init_string[64];
|
||||||
char dial_string[64];
|
char dial_string[64];
|
||||||
char escape_string[8];
|
char escape_string[8];
|
||||||
@@ -51,6 +52,123 @@ struct dialup_device : net_device {
|
|||||||
net_buffer_module_info* gBufferModule;
|
net_buffer_module_info* gBufferModule;
|
||||||
static net_stack_module_info* sStackModule;
|
static net_stack_module_info* sStackModule;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
send_command(dialup_device* device, const char* command)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
if (device->data_mode) {
|
||||||
|
status = switch_to_command_mode(device);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t bytesWritten = write(device->fd, command, strlen(command);
|
||||||
|
if (bytesWritten != (ssize_t)strlen(command))
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
if (write(fd, "\r", 1) != 1)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
read_command_reply(dialup_device* device, const char* command,
|
||||||
|
char* reply, int replyMaxSize)
|
||||||
|
{
|
||||||
|
if (device->data_mode)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (i < replyMaxSize) {
|
||||||
|
|
||||||
|
ssize_t bytesRead = read(device->fd, &reply[i], 1);
|
||||||
|
if (bytesRead != 1)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
if (reply[i] == '\n') {
|
||||||
|
// filter linefeed char
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply[i] == '\r') {
|
||||||
|
reply[i] = '\0';
|
||||||
|
|
||||||
|
// is command reply or command echo (if any) ?
|
||||||
|
if (!strcasecmp(reply, command))
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// It's command echo line. Just ignore it.
|
||||||
|
i = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// replyMaxSize not large enough to store the full reply line.
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
switch_to_command_mode(dialup_device* device)
|
||||||
|
{
|
||||||
|
if (device->state != UP || !device->data_mode)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
snooze(device->escape_silence);
|
||||||
|
|
||||||
|
ssize_t size = write(device->fd, device->escape_string,
|
||||||
|
strlen(device->escape_string));
|
||||||
|
if (size != (ssize_t)strlen(device->escape_string))
|
||||||
|
return B_IO_ERROR;
|
||||||
|
|
||||||
|
snooze(device->escape_silence);
|
||||||
|
device->data_mode = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
switch_to_data_mode(dialup_device* device)
|
||||||
|
{
|
||||||
|
if (device->state != UP)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// TODO: check if it's needed, as these days any
|
||||||
|
// escaped AT commands switch back to data mode automatically
|
||||||
|
// after their completion...
|
||||||
|
status_t status = send_command(device, "ATO");
|
||||||
|
if (status == B_OK);
|
||||||
|
device->data_mode = true;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
hangup_device(dialup_device* device)
|
||||||
|
{
|
||||||
|
if (device->state != UP)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// TODO: turn device's DTR down instead. Or do that too after sending command
|
||||||
|
char reply[8];
|
||||||
|
if (send_command(device, device->hangup_string) != B_OK
|
||||||
|
|| read_command_reply(device, device->hangup_string,
|
||||||
|
reply, sizeof(reply)) != B_OK
|
||||||
|
|| strcmp(reply, "OK"))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
device->flags &= ~IFF_LINK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -81,6 +199,7 @@ dialup_init(const char* name, net_device** _device)
|
|||||||
device->header_length = 8; // HDLC_HEADER_LENGTH;
|
device->header_length = 8; // HDLC_HEADER_LENGTH;
|
||||||
device->fd = -1;
|
device->fd = -1;
|
||||||
device->state = DOWN;
|
device->state = DOWN;
|
||||||
|
device->data_mode = false;
|
||||||
|
|
||||||
// default AT strings
|
// default AT strings
|
||||||
strncpy(device->init_string, "ATZ", sizeof(device->init_string));
|
strncpy(device->init_string, "ATZ", sizeof(device->init_string));
|
||||||
@@ -115,6 +234,8 @@ dialup_up(net_device* _device)
|
|||||||
if (device->fd < 0)
|
if (device->fd < 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
|
device->media = IFM_ACTIVE;
|
||||||
|
|
||||||
// init port
|
// init port
|
||||||
if (ioctl(device->fd, TCGETA, &device->line_config,
|
if (ioctl(device->fd, TCGETA, &device->line_config,
|
||||||
sizeof(device->line_config)) < 0)
|
sizeof(device->line_config)) < 0)
|
||||||
@@ -136,11 +257,44 @@ dialup_up(net_device* _device)
|
|||||||
|
|
||||||
// TODO: init modem & start dialing phase
|
// TODO: init modem & start dialing phase
|
||||||
device->state = DIALING;
|
device->state = DIALING;
|
||||||
|
|
||||||
|
char reply[32];
|
||||||
|
|
||||||
|
// Send modem init string
|
||||||
|
if (send_command(device, device->init_string) != B_OK
|
||||||
|
|| read_command_reply(device, device->init_string,
|
||||||
|
reply, sizeof(reply)) != B_OK
|
||||||
|
|| strcmp(reply, "OK")) {
|
||||||
|
errno = B_IO_ERROR;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send dialing string
|
||||||
|
if (send_command(device, device->dialing_string) != B_OK
|
||||||
|
|| read_command_reply(device, device->dialing_string,
|
||||||
|
reply, sizeof(reply)) != B_OK
|
||||||
|
|| strncmp(reply, "CONNECT", 7)) {
|
||||||
|
errno = B_IO_ERROR;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
device->data_mode = true;
|
||||||
|
|
||||||
|
device->media |= IFM_FULL_DUPLEX
|
||||||
|
device->flags |= IFF_LINK;
|
||||||
|
|
||||||
|
device->link_quality = 1000;
|
||||||
|
if (strlen(reply) > 7) {
|
||||||
|
device->link_speed = atoi(&reply[8]);
|
||||||
|
else
|
||||||
|
device->link_speed = 19200; // check default baudrate
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
close(device->fd);
|
close(device->fd);
|
||||||
device->fd = -1;
|
device->fd = -1;
|
||||||
|
device->media = 0;
|
||||||
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,18 +304,9 @@ dialup_down(net_device* _device)
|
|||||||
{
|
{
|
||||||
dialup_device* device = (dialup_device*)_device;
|
dialup_device* device = (dialup_device*)_device;
|
||||||
|
|
||||||
// TODO: hangup if needed
|
if (device->flags & IFF_LINK &&
|
||||||
if (device->flags & IFF_LINK) {
|
hangup_device(device) == B_OK)
|
||||||
snooze(device->escape_silence);
|
|
||||||
if (write(device->fd, device->escape_string,
|
|
||||||
strlen(device->escape_string)) > 0) {
|
|
||||||
snooze(device->escape_silence);
|
|
||||||
// TODO: send hangup string and check for OK ack
|
|
||||||
write(device->fd, device->hangup_string,
|
|
||||||
strlen(device->hangup_string));
|
|
||||||
}
|
|
||||||
device->flags &= ~IFF_LINK;
|
device->flags &= ~IFF_LINK;
|
||||||
}
|
|
||||||
|
|
||||||
close(device->fd);
|
close(device->fd);
|
||||||
device->fd = -1;
|
device->fd = -1;
|
||||||
|
|||||||
@@ -265,11 +265,11 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length)
|
|||||||
if ((mediareq.ifm_status & IFM_ACTIVE) != 0)
|
if ((mediareq.ifm_status & IFM_ACTIVE) != 0)
|
||||||
state.media |= IFM_ACTIVE;
|
state.media |= IFM_ACTIVE;
|
||||||
if ((mediareq.ifm_active & IFM_10_T) != 0)
|
if ((mediareq.ifm_active & IFM_10_T) != 0)
|
||||||
state.speed = 10000;
|
state.speed = 10000000;
|
||||||
else if ((mediareq.ifm_active & IFM_100_TX) != 0)
|
else if ((mediareq.ifm_active & IFM_100_TX) != 0)
|
||||||
state.speed = 100000;
|
state.speed = 100000000;
|
||||||
else
|
else
|
||||||
state.speed = 1000000;
|
state.speed = 1000000000;
|
||||||
state.quality = 1000;
|
state.quality = 1000;
|
||||||
|
|
||||||
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
|
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
|
||||||
|
|||||||
Reference in New Issue
Block a user