4 * Copyright 2006, Haiku, Inc. All Rights Reserved.
5 * Distributed under the terms of the MIT License.
18 typedef struct driver_cookie
{
19 struct driver_cookie
*next
;
23 int32 api_version
= B_CUR_DRIVER_API_VERSION
;
25 static status_t
pegasus_device_added(const usb_device dev
, void **cookie
);
26 static status_t
pegasus_device_removed(void *cookie
);
28 static int sDeviceNumber
= 0;
29 static const char *kBaseName
= "net/pegasus/";
31 static const char *kDriverName
= DRIVER_NAME
;
36 usb_support_descriptor supported_devices
[] = {
37 { 0, 0, 0, USB_VENDOR_3COM
, USB_PRODUCT_3COM_3C460B
},
38 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX1
},
39 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX2
},
40 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_UFE1000
},
41 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX4
},
42 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX5
},
43 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX6
},
44 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX7
},
45 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX8
},
46 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX9
},
47 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX10
},
48 { 0, 0, 0, USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_DSB650TX_PNA
},
49 { 0, 0, 0, USB_VENDOR_ACCTON
, USB_PRODUCT_ACCTON_USB320_EC
},
50 { 0, 0, 0, USB_VENDOR_ACCTON
, USB_PRODUCT_ACCTON_SS1001
},
51 { 0, 0, 0, USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUS
},
52 { 0, 0, 0, USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII
},
53 { 0, 0, 0, USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII_2
},
54 { 0, 0, 0, USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII_3
},
55 { 0, 0, 0, USB_VENDOR_BELKIN
, USB_PRODUCT_BELKIN_USB2LAN
},
56 { 0, 0, 0, USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USB100
},
57 { 0, 0, 0, USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBLP100
},
58 { 0, 0, 0, USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBEL100
},
59 { 0, 0, 0, USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBE100
},
60 { 0, 0, 0, USB_VENDOR_COREGA
, USB_PRODUCT_COREGA_FETHER_USB_TX
},
61 { 0, 0, 0, USB_VENDOR_COREGA
, USB_PRODUCT_COREGA_FETHER_USB_TXS
},
62 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX4
},
63 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX1
},
64 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX
},
65 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX_PNA
},
66 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX3
},
67 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX2
},
68 { 0, 0, 0, USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650
},
69 { 0, 0, 0, USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX0
},
70 { 0, 0, 0, USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX1
},
71 { 0, 0, 0, USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX2
},
72 { 0, 0, 0, USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX3
},
73 { 0, 0, 0, USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBLTX
},
74 { 0, 0, 0, USB_VENDOR_ELSA
, USB_PRODUCT_ELSA_USB2ETHERNET
},
75 { 0, 0, 0, USB_VENDOR_HAWKING
, USB_PRODUCT_HAWKING_UF100
},
76 { 0, 0, 0, USB_VENDOR_HP
, USB_PRODUCT_HP_HN210E
},
77 { 0, 0, 0, USB_VENDOR_IODATA
, USB_PRODUCT_IODATA_USBETTX
},
78 { 0, 0, 0, USB_VENDOR_IODATA
, USB_PRODUCT_IODATA_USBETTXS
},
79 { 0, 0, 0, USB_VENDOR_KINGSTON
, USB_PRODUCT_KINGSTON_KNU101TX
},
80 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TX1
},
81 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10T
},
82 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB100TX
},
83 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB100H1
},
84 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TA
},
85 { 0, 0, 0, USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TX2
},
86 { 0, 0, 0, USB_VENDOR_MICROSOFT
, USB_PRODUCT_MICROSOFT_MN110
},
87 { 0, 0, 0, USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUATX1
},
88 { 0, 0, 0, USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUATX5
},
89 { 0, 0, 0, USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUA2TX5
},
90 { 0, 0, 0, USB_VENDOR_NETGEAR
, USB_PRODUCT_NETGEAR_FA101
},
91 { 0, 0, 0, USB_VENDOR_SIEMENS
, USB_PRODUCT_SIEMENS_SPEEDSTREAM
},
92 { 0, 0, 0, USB_VENDOR_SMARTBRIDGES
, USB_PRODUCT_SMARTBRIDGES_SMARTNIC
},
93 { 0, 0, 0, USB_VENDOR_SMC
, USB_PRODUCT_SMC_2202USB
},
94 { 0, 0, 0, USB_VENDOR_SMC
, USB_PRODUCT_SMC_2206USB
},
95 { 0, 0, 0, USB_VENDOR_SOHOWARE
, USB_PRODUCT_SOHOWARE_NUB100
},
99 static const struct aue_type aue_devs
[] = {
100 {{ USB_VENDOR_3COM
, USB_PRODUCT_3COM_3C460B
}, PII
},
101 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX1
}, PNA
|PII
},
102 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX2
}, PII
},
103 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_UFE1000
}, LSYS
},
104 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX4
}, PNA
},
105 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX5
}, PNA
},
106 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX6
}, PII
},
107 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX7
}, PII
},
108 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX8
}, PII
},
109 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX9
}, PNA
},
110 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_XX10
}, 0 },
111 {{ USB_VENDOR_ABOCOM
, USB_PRODUCT_ABOCOM_DSB650TX_PNA
}, 0 },
112 {{ USB_VENDOR_ACCTON
, USB_PRODUCT_ACCTON_USB320_EC
}, 0 },
113 {{ USB_VENDOR_ACCTON
, USB_PRODUCT_ACCTON_SS1001
}, PII
},
114 {{ USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUS
}, PNA
},
115 {{ USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII
}, PII
},
116 {{ USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII_2
}, PII
},
117 {{ USB_VENDOR_ADMTEK
, USB_PRODUCT_ADMTEK_PEGASUSII_3
}, PII
},
118 {{ USB_VENDOR_BELKIN
, USB_PRODUCT_BELKIN_USB2LAN
}, PII
},
119 {{ USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USB100
}, 0 },
120 {{ USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBLP100
}, PNA
},
121 {{ USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBEL100
}, 0 },
122 {{ USB_VENDOR_BILLIONTON
, USB_PRODUCT_BILLIONTON_USBE100
}, PII
},
123 {{ USB_VENDOR_COREGA
, USB_PRODUCT_COREGA_FETHER_USB_TX
}, 0 },
124 {{ USB_VENDOR_COREGA
, USB_PRODUCT_COREGA_FETHER_USB_TXS
},PII
},
125 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX4
}, LSYS
|PII
},
126 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX1
}, LSYS
},
127 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX
}, LSYS
},
128 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX_PNA
}, PNA
},
129 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX3
}, LSYS
|PII
},
130 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650TX2
}, LSYS
|PII
},
131 {{ USB_VENDOR_DLINK
, USB_PRODUCT_DLINK_DSB650
}, LSYS
},
132 {{ USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX0
}, 0 },
133 {{ USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX1
}, LSYS
},
134 {{ USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX2
}, 0 },
135 {{ USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBTX3
}, LSYS
},
136 {{ USB_VENDOR_ELECOM
, USB_PRODUCT_ELECOM_LDUSBLTX
}, PII
},
137 {{ USB_VENDOR_ELSA
, USB_PRODUCT_ELSA_USB2ETHERNET
}, 0 },
138 {{ USB_VENDOR_HAWKING
, USB_PRODUCT_HAWKING_UF100
}, PII
},
139 {{ USB_VENDOR_HP
, USB_PRODUCT_HP_HN210E
}, PII
},
140 {{ USB_VENDOR_IODATA
, USB_PRODUCT_IODATA_ETXUS2
}, PII
},
141 {{ USB_VENDOR_IODATA
, USB_PRODUCT_IODATA_USBETTX
}, 0 },
142 {{ USB_VENDOR_IODATA
, USB_PRODUCT_IODATA_USBETTXS
}, PII
},
143 {{ USB_VENDOR_KINGSTON
, USB_PRODUCT_KINGSTON_KNU101TX
}, 0 },
144 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TX1
}, LSYS
|PII
},
145 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10T
}, LSYS
},
146 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB100TX
}, LSYS
},
147 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB100H1
}, LSYS
|PNA
},
148 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TA
}, LSYS
},
149 {{ USB_VENDOR_LINKSYS
, USB_PRODUCT_LINKSYS_USB10TX2
}, LSYS
|PII
},
150 {{ USB_VENDOR_MICROSOFT
, USB_PRODUCT_MICROSOFT_MN110
}, PII
},
151 {{ USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUATX1
}, 0 },
152 {{ USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUATX5
}, 0 },
153 {{ USB_VENDOR_MELCO
, USB_PRODUCT_MELCO_LUA2TX5
}, PII
},
154 {{ USB_VENDOR_NETGEAR
, USB_PRODUCT_NETGEAR_FA101
}, PII
},
155 {{ USB_VENDOR_SIEMENS
, USB_PRODUCT_SIEMENS_SPEEDSTREAM
}, PII
},
156 {{ USB_VENDOR_SMARTBRIDGES
, USB_PRODUCT_SMARTBRIDGES_SMARTNIC
},PII
},
157 {{ USB_VENDOR_SMC
, USB_PRODUCT_SMC_2202USB
}, 0 },
158 {{ USB_VENDOR_SMC
, USB_PRODUCT_SMC_2206USB
}, PII
},
159 {{ USB_VENDOR_SOHOWARE
, USB_PRODUCT_SOHOWARE_NUB100
}, 0 },
164 pegasus_checkdeviceinfo(pegasus_dev
*dev
)
166 if (!dev
|| dev
->cookieMagic
!= PEGASUS_COOKIE_MAGIC
)
174 create_device(const usb_device dev
, const usb_interface_info
*ii
, uint16 ifno
)
176 pegasus_dev
*device
= NULL
;
179 ASSERT(usb
!= NULL
&& dev
!= 0);
181 device
= malloc(sizeof(pegasus_dev
));
185 memset(device
, 0, sizeof(pegasus_dev
));
187 device
->sem_lock
= sem
= create_sem(1, DRIVER_NAME
"_lock");
189 DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32
"\n", sem
);
194 device
->rx_sem
= sem
= create_sem(1, DRIVER_NAME
"_receive");
196 DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32
"\n", sem
);
197 delete_sem(device
->sem_lock
);
201 set_sem_owner(device
->rx_sem
, B_SYSTEM_TEAM
);
203 device
->rx_sem_cb
= sem
= create_sem(0, DRIVER_NAME
"_receive_cb");
205 DPRINTF_ERR("create_sem() failed 0x%" B_PRIx32
"\n", sem
);
206 delete_sem(device
->rx_sem
);
207 delete_sem(device
->sem_lock
);
211 set_sem_owner(device
->rx_sem_cb
, B_SYSTEM_TEAM
);
213 device
->tx_sem
= sem
= create_sem(1, DRIVER_NAME
"_transmit");
215 delete_sem(device
->sem_lock
);
216 delete_sem(device
->rx_sem
);
217 delete_sem(device
->rx_sem_cb
);
221 set_sem_owner(device
->tx_sem
, B_SYSTEM_TEAM
);
223 device
->tx_sem_cb
= sem
= create_sem(0, DRIVER_NAME
"_transmit_cb");
225 delete_sem(device
->sem_lock
);
226 delete_sem(device
->rx_sem
);
227 delete_sem(device
->rx_sem_cb
);
228 delete_sem(device
->tx_sem
);
232 set_sem_owner(device
->tx_sem_cb
, B_SYSTEM_TEAM
);
234 device
->number
= sDeviceNumber
++;
235 device
->cookieMagic
= PEGASUS_COOKIE_MAGIC
;
236 sprintf(device
->name
, "%s%d", kBaseName
, device
->number
);
240 device
->open_fds
= NULL
;
241 device
->aue_dying
= false;
243 device
->maxframesize
= 1514; // XXX is MAXIMUM_ETHERNET_FRAME_SIZE = 1518 too much?
250 remove_device(pegasus_dev
*device
)
252 ASSERT(device
!= NULL
);
254 delete_sem(device
->rx_sem
);
255 delete_sem(device
->tx_sem
);
256 delete_sem(device
->rx_sem_cb
);
257 delete_sem(device
->tx_sem_cb
);
259 delete_sem(device
->sem_lock
);
269 setup_endpoints(const usb_interface_info
*uii
, pegasus_dev
*dev
)
271 size_t epts
[3] = { -1, -1, -1 };
273 for(; ep
< uii
->endpoint_count
; ep
++){
274 usb_endpoint_descriptor
*ed
= uii
->endpoint
[ep
].descr
;
275 DPRINTF_INFO("try endpoint:%ld %x %x %lx\n", ep
, ed
->attributes
,
276 ed
->endpoint_address
, uii
->endpoint
[ep
].handle
);
277 if ((ed
->attributes
& USB_ENDPOINT_ATTR_MASK
) == USB_ENDPOINT_ATTR_BULK
) {
278 if ((ed
->endpoint_address
& USB_ENDPOINT_ADDR_DIR_IN
)
279 == USB_ENDPOINT_ADDR_DIR_IN
) {
283 } else if ((ed
->attributes
& USB_ENDPOINT_ATTR_MASK
)
284 == USB_ENDPOINT_ATTR_INTERRUPT
) {
289 dev
->pipe_in
= uii
->endpoint
[epts
[0]].handle
;
290 dev
->pipe_out
= uii
->endpoint
[epts
[1]].handle
;
291 dev
->pipe_intr
= uii
->endpoint
[epts
[2]].handle
;
292 DPRINTF_INFO("endpoint:%lx %lx %lx\n", dev
->pipe_in
, dev
->pipe_out
, dev
->pipe_intr
);
294 return ((epts
[0] > -1) && (epts
[1] > -1) && (epts
[2] > -1)) ? B_OK
: B_ENTRY_NOT_FOUND
;
299 pegasus_rx_callback(void *cookie
, status_t status
, void *data
, size_t actual_len
)
301 pegasus_dev
*dev
= (pegasus_dev
*)cookie
;
303 DPRINTF_INFO("pegasus_rx_callback() %ld %ld\n", status
, actual_len
);
304 if (status
== B_CANCELED
) {
305 /* cancelled: device is unplugged */
306 DPRINTF_ERR("pegasus_rx_callback() cancelled\n");
310 ASSERT(cookie
!= NULL
);
311 dev
->rx_actual_length
= actual_len
;
312 dev
->rx_status
= status
; /* B_USB_STATUS_* */
313 release_sem(dev
->rx_sem_cb
);
314 DPRINTF_INFO("pegasus_rx_callback release sem %ld\n", dev
->rx_sem_cb
);
319 pegasus_tx_callback(void *cookie
, status_t status
, void *data
, size_t actual_len
)
321 pegasus_dev
*dev
= (pegasus_dev
*)cookie
;
323 DPRINTF_INFO("pegasus_tx_callback() %ld %ld\n", status
, actual_len
);
324 if (status
== B_CANCELED
) {
325 /* cancelled: device is unplugged */
326 DPRINTF_ERR("pegasus_tx_callback() cancelled\n");
330 ASSERT(cookie
!= NULL
);
331 dev
->tx_actual_length
= actual_len
;
332 dev
->tx_status
= status
; /* B_USB_STATUS_* */
333 release_sem(dev
->tx_sem_cb
);
334 DPRINTF_INFO("pegasus_tx_callback release sem %ld\n", dev
->tx_sem_cb
);
338 // #pragma mark - device hooks
342 pegasus_device_added(const usb_device dev
, void **cookie
)
345 const usb_device_descriptor
*dev_desc
;
346 const usb_configuration_info
*conf
;
347 const usb_interface_info
*intf
;
352 ASSERT(dev
!= 0 && cookie
!= NULL
);
353 DPRINTF_INFO("device_added()\n");
355 dev_desc
= usb
->get_device_descriptor(dev
);
357 DPRINTF_INFO("vendor ID 0x%04X, product ID 0x%04X\n", dev_desc
->vendor_id
,
358 dev_desc
->product_id
);
360 if ((conf
= usb
->get_nth_configuration(dev
, DEFAULT_CONFIGURATION
))
362 DPRINTF_ERR("cannot get default configuration\n");
366 ifno
= AUE_IFACE_IDX
;
367 intf
= conf
->interface
[ifno
].active
;
371 if ((status
= usb
->set_configuration(dev
, conf
)) != B_OK
) {
372 DPRINTF_ERR("set_configuration() failed %s\n", strerror(status
));
376 if ((device
= create_device(dev
, intf
, ifno
)) == NULL
) {
377 DPRINTF_ERR("create_device() failed\n");
381 device
->aue_vendor
= dev_desc
->vendor_id
;
382 device
->aue_product
= dev_desc
->product_id
;
384 for (i
=0; i
< sizeof(aue_devs
) / sizeof(struct aue_type
); i
++)
385 if (aue_devs
[i
].aue_dev
.vendor
== dev_desc
->vendor_id
386 && aue_devs
[i
].aue_dev
.product
== dev_desc
->product_id
) {
387 device
->aue_flags
= aue_devs
[i
].aue_flags
;
391 /* Find endpoints. */
392 setup_endpoints(intf
, device
);
396 DPRINTF_INFO("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
397 device
->macaddr
[0], device
->macaddr
[1], device
->macaddr
[2],
398 device
->macaddr
[3], device
->macaddr
[4], device
->macaddr
[5]);
403 add_device_info(device
);
406 DPRINTF_INFO("added %s\n", device
->name
);
412 pegasus_device_removed(void *cookie
)
414 pegasus_dev
*device
= cookie
;
416 ASSERT(cookie
!= NULL
);
418 DPRINTF_INFO("device_removed(%s)\n", device
->name
);
422 usb
->cancel_queued_transfers(device
->pipe_in
);
423 usb
->cancel_queued_transfers(device
->pipe_out
);
424 usb
->cancel_queued_transfers(device
->pipe_intr
);
425 remove_device_info(device
);
427 if (device
->open
== 0) {
428 remove_device(device
);
430 DPRINTF_INFO("%s still open\n", device
->name
);
432 device
->aue_dying
= true;
441 pegasus_device_open(const char *name
, uint32 flags
,
442 driver_cookie
**out_cookie
)
444 driver_cookie
*cookie
;
448 ASSERT(name
!= NULL
);
449 ASSERT(out_cookie
!= NULL
);
450 DPRINTF_INFO("open(%s)\n", name
);
452 if ((device
= search_device_info(name
)) == NULL
)
453 return B_ENTRY_NOT_FOUND
;
454 if ((cookie
= malloc(sizeof(driver_cookie
))) == NULL
)
457 if ((err
= acquire_sem(device
->sem_lock
)) != B_OK
) {
461 device
->nonblocking
= (flags
& O_NONBLOCK
) != 0;
463 cookie
->device
= device
;
464 cookie
->next
= device
->open_fds
;
465 device
->open_fds
= cookie
;
467 release_sem(device
->sem_lock
);
469 *out_cookie
= cookie
;
470 DPRINTF_INFO("device %s open (%d)\n", name
, device
->open
);
476 pegasus_device_read(driver_cookie
*cookie
, off_t position
, void *buffer
, size_t *_length
)
483 DPRINTF_INFO("device %p read\n", cookie
);
485 if (pegasus_checkdeviceinfo(dev
= cookie
->device
) != B_OK
) {
486 DPRINTF_ERR("EINVAL\n");
489 // net_server work-around; it obviously doesn't care about error conditions
490 // For Haiku, this can be removed
496 return B_DEVICE_NOT_FOUND
; /* already unplugged */
498 blockFlag
= dev
->nonblocking
? B_TIMEOUT
: 0;
500 // block until receive is available (if blocking is allowed)
501 if ((status
= acquire_sem_etc(dev
->rx_sem
, 1, B_CAN_INTERRUPT
| blockFlag
, 0)) != B_NO_ERROR
) {
502 DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32
", %s\n", status
, strerror(status
));
510 status
= usb
->queue_bulk(dev
->pipe_in
, dev
->rx_buffer
, MAX_FRAME_SIZE
, &pegasus_rx_callback
, dev
);
512 if (status
!= B_OK
) {
513 DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32
"\n", status
);
517 // block until data is available (if blocking is allowed)
518 if ((status
= acquire_sem_etc(dev
->rx_sem_cb
, 1, B_CAN_INTERRUPT
| blockFlag
, 0)) != B_NO_ERROR
) {
519 DPRINTF_ERR("cannot acquire read sem: %" B_PRIx32
", %s\n", status
, strerror(status
));
526 if (dev
->rx_status
!= B_OK
) {
527 status
= usb
->clear_feature(dev
->pipe_in
, USB_FEATURE_ENDPOINT_HALT
);
529 DPRINTF_ERR("clear_feature() error %s\n", strerror(status
));
534 size
= dev
->rx_actual_length
;
535 if (size
> MAX_FRAME_SIZE
|| (size
- 2) > *_length
) {
536 DPRINTF_ERR("ERROR read: bad frame size %ld\n", size
);
538 } else if (size
< *_length
)
541 memcpy(buffer
, dev
->rx_buffer
, size
);
543 DPRINTF_INFO("read done %ld\n", *_length
);
546 release_sem(dev
->rx_sem
);
552 pegasus_device_write(driver_cookie
*cookie
, off_t position
, const void *buffer
, size_t *_length
)
558 DPRINTF_INFO("device %p write %ld\n", cookie
, *_length
);
560 if (pegasus_checkdeviceinfo(dev
= cookie
->device
) != B_OK
) {
561 DPRINTF_ERR("EINVAL\n");
566 return B_DEVICE_NOT_FOUND
; /* already unplugged */
568 // block until a free tx descriptor is available
569 if ((status
= acquire_sem_etc(dev
->tx_sem
, 1, B_TIMEOUT
, ETHER_TRANSMIT_TIMEOUT
)) < B_NO_ERROR
) {
570 DPRINTF_ERR("write: acquiring sem failed: %" B_PRIx32
", %s\n", status
, strerror(status
));
575 if (*_length
> MAX_FRAME_SIZE
)
576 *_length
= MAX_FRAME_SIZE
;
578 frameSize
= *_length
;
580 /* Copy data to tx buffer */
581 memcpy(dev
->tx_buffer
+2, buffer
, frameSize
);
584 * The ADMtek documentation says that the packet length is
585 * supposed to be specified in the first two bytes of the
586 * transfer, however it actually seems to ignore this info
587 * and base the frame size on the bulk transfer length.
589 dev
->tx_buffer
[0] = (uint8
)frameSize
;
590 dev
->tx_buffer
[1] = (uint8
)(frameSize
>> 8);
592 // queue new request, bulk length is one more if size is a multiple of 64
593 status
= usb
->queue_bulk(dev
->pipe_out
, dev
->tx_buffer
, ((frameSize
+ 2) & 0x3f) ? frameSize
+ 2 : frameSize
+ 3,
594 &pegasus_tx_callback
, dev
);
597 DPRINTF_ERR("queue_bulk:failed:%08" B_PRIx32
"\n", status
);
601 // block until data is sent (if blocking is allowed)
602 if ((status
= acquire_sem_etc(dev
->tx_sem_cb
, 1, B_CAN_INTERRUPT
, 0)) != B_NO_ERROR
) {
603 DPRINTF_ERR("cannot acquire write done sem: %" B_PRIx32
", %s\n", status
, strerror(status
));
610 if (dev
->tx_status
!= B_OK
) {
611 status
= usb
->clear_feature(dev
->pipe_out
, USB_FEATURE_ENDPOINT_HALT
);
613 DPRINTF_ERR("clear_feature() error %s\n", strerror(status
));
617 *_length
= frameSize
;
620 release_sem(dev
->tx_sem
);
626 pegasus_device_control(driver_cookie
*cookie
, uint32 op
,
627 void *arg
, size_t len
)
629 status_t err
= B_ERROR
;
632 ASSERT(cookie
!= NULL
);
633 device
= cookie
->device
;
634 ASSERT(device
!= NULL
);
635 DPRINTF_INFO("ioctl(0x%x)\n", (int)op
);
637 if (device
->aue_dying
)
638 return B_DEVICE_NOT_FOUND
; /* already unplugged */
642 DPRINTF_INFO("control() ETHER_INIT\n");
646 DPRINTF_INFO("control() ETHER_GETADDR\n");
647 memcpy(arg
, &device
->macaddr
, sizeof(device
->macaddr
));
652 DPRINTF_INFO("non blocking mode on\n");
653 device
->nonblocking
= true;
655 DPRINTF_INFO("non blocking mode off\n");
656 device
->nonblocking
= false;
661 DPRINTF_INFO("control() ETHER_ADDMULTI\n");
665 DPRINTF_INFO("control() ETHER_REMMULTI\n");
668 case ETHER_SETPROMISC
:
670 DPRINTF_INFO("control() ETHER_SETPROMISC on\n");
672 DPRINTF_INFO("control() ETHER_SETPROMISC off\n");
676 case ETHER_GETFRAMESIZE
:
677 DPRINTF_INFO("control() ETHER_GETFRAMESIZE, framesize = %ld (MTU = %ld)\n", device
->maxframesize
, device
->maxframesize
- ENET_HEADER_SIZE
);
678 *(uint32
*)arg
= device
->maxframesize
;
682 DPRINTF_INFO("control() Invalid command\n");
691 pegasus_device_close(driver_cookie
*cookie
)
695 ASSERT(cookie
!= NULL
&& cookie
->device
!= NULL
);
696 device
= cookie
->device
;
697 DPRINTF_INFO("close(%s)\n", device
->name
);
699 /* detach the cookie from list */
701 acquire_sem(device
->sem_lock
);
702 if (device
->open_fds
== cookie
)
703 device
->open_fds
= cookie
->next
;
706 for (p
= device
->open_fds
; p
!= NULL
; p
= p
->next
) {
707 if (p
->next
== cookie
) {
708 p
->next
= cookie
->next
;
714 release_sem(device
->sem_lock
);
721 pegasus_device_free(driver_cookie
*cookie
)
725 ASSERT(cookie
!= NULL
&& cookie
->device
!= NULL
);
726 device
= cookie
->device
;
727 DPRINTF_INFO("free(%s)\n", device
->name
);
730 if (device
->open
> 0)
731 DPRINTF_INFO("%d opens left\n", device
->open
);
732 else if (device
->aue_dying
) {
733 DPRINTF_INFO("removed %s\n", device
->name
);
734 remove_device(device
);
742 /* Driver Hooks ---------------------------------------------------------
744 ** These functions provide the glue used by DevFS to load/unload
745 ** the driver and also handle registering with the USB bus manager
746 ** to receive device added and removed events
749 static usb_notify_hooks notify_hooks
=
751 &pegasus_device_added
,
752 &pegasus_device_removed
766 DPRINTF_INFO("init_driver(), built %s %s\n", __DATE__
, __TIME__
);
769 if (load_driver_symbols(drivername
) == B_OK
) {
770 DPRINTF_INFO("loaded symbols\n");
772 DPRINTF_INFO("no symbols for you!\n");
776 if (get_module(B_USB_MODULE_NAME
, (module_info
**) &usb
) != B_OK
) {
777 DPRINTF_INFO("cannot get module \"%s\"\n", B_USB_MODULE_NAME
);
781 if ((gDeviceListLock
= create_sem(1, "dev_list_lock")) < 0) {
782 put_module(B_USB_MODULE_NAME
);
783 return gDeviceListLock
;
786 usb
->register_driver(kDriverName
, supported_devices
,
787 sizeof(supported_devices
)/sizeof(usb_support_descriptor
), NULL
);
788 usb
->install_notify(kDriverName
, ¬ify_hooks
);
797 DPRINTF_INFO("uninit_driver()\n");
799 usb
->uninstall_notify(kDriverName
);
800 delete_sem(gDeviceListLock
);
801 put_module(B_USB_MODULE_NAME
);
807 publish_devices(void)
809 if (gDeviceListChanged
) {
811 alloc_device_names();
812 if (gDeviceNames
!= NULL
)
813 rebuild_device_names();
814 gDeviceListChanged
= false;
816 ASSERT(gDeviceNames
!= NULL
);
817 return (const char **) gDeviceNames
;
822 find_device(const char* name
)
824 static device_hooks hooks
= {
825 (device_open_hook
)pegasus_device_open
,
826 (device_close_hook
)pegasus_device_close
,
827 (device_free_hook
)pegasus_device_free
,
828 (device_control_hook
)pegasus_device_control
,
829 (device_read_hook
)pegasus_device_read
,
830 (device_write_hook
)pegasus_device_write
,
834 if (search_device_info(name
) != NULL
)